423e7e8dVDL1WLfbmQWuXMbetYk4jA freebsd-5.3-xen-sparse/mkbuildtree
423e7e8dBrOrAbydK6h49bY0VvDgPw freebsd-5.3-xen-sparse/xenfbsd_kernel_build
4187ca95_eQN62ugV1zliQcfzXrHnw install.sh
- 3e5a4e6589G-U42lFKs43plskXoFxQ linux-2.4.29-xen-sparse/Makefile
- 3e5a4e65IEPjnWPZ5w3TxS5scV8Ewg linux-2.4.29-xen-sparse/arch/xen/Makefile
- 3e5a4e65n-KhsEAs-A4ULiStBp-r6w linux-2.4.29-xen-sparse/arch/xen/boot/Makefile
- 3e5a4e65OV_j_DBtjzt5vej771AJsA linux-2.4.29-xen-sparse/arch/xen/config.in
- 40648526SxcA4lGIHB_k7ID8VlRSzw linux-2.4.29-xen-sparse/arch/xen/defconfig-xen0
- 40c73c77QesbL7eIvG-fJGAtVwhGRg linux-2.4.29-xen-sparse/arch/xen/defconfig-xenU
- 3e6377f5xwPfYZkPHPrDbEq1PRN7uQ linux-2.4.29-xen-sparse/arch/xen/drivers/balloon/Makefile
- 4083dc16z0jvZEH4PiVDbDRreaNp6w linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/Makefile
- 4083dc16KQus88a4U3uCV6qVCA6_8Q linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/backend/Makefile
- 4075806dI5kfeMD5RV-DA0PYoThx_w linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/Makefile
- 4075806d4-j7vN0Mn0bklI1cRUX1vQ linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/common.h
- 4075806dibjCcfuXv6CINMhxWTw3jQ linux-2.4.29-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c
- 3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ linux-2.4.29-xen-sparse/arch/xen/drivers/console/Makefile
- 3e5a4e656nfFISThfbyXQOA6HN6YHw linux-2.4.29-xen-sparse/arch/xen/drivers/dom0/Makefile
- 40420a6ebRqDjufoN1WSJvolEW2Wjw linux-2.4.29-xen-sparse/arch/xen/drivers/evtchn/Makefile
- 4083dc16-Kd5y9psK_yk161sme5j5Q linux-2.4.29-xen-sparse/arch/xen/drivers/netif/Makefile
- 4083dc16UmHXxS9g_UFVnkUpN-oP2Q linux-2.4.29-xen-sparse/arch/xen/drivers/netif/backend/Makefile
- 405853f2wg7JXZJNltspMwOZJklxgw linux-2.4.29-xen-sparse/arch/xen/drivers/netif/frontend/Makefile
+41ee5e8b_2rt-qHzbDXtIoBzOli0EA linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/Makefile
+41ee5e8bUhF4tH7OoJaVbUxdXqneVw linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/backend/Makefile
+41ee5e8bSPpxzhGO6TrY20TegW3cZg linux-2.4.29-xen-sparse/arch/xen/drivers/usbif/frontend/Makefile
- 3e5a4e65lWzkiPXsZdzPt2RNnJGG1g linux-2.4.29-xen-sparse/arch/xen/kernel/Makefile
- 3e5a4e65_hqfuxtGG8IUy6wRM86Ecg linux-2.4.29-xen-sparse/arch/xen/kernel/entry.S
- 3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg linux-2.4.29-xen-sparse/arch/xen/kernel/head.S
- 3e5a4e65RMGcuA-HCn3-wNx3fFQwdg linux-2.4.29-xen-sparse/arch/xen/kernel/i386_ksyms.c
+4241709bNBs1q4Ss32YW0CyFVOGhEg linux-2.4.29-xen-sparse/arch/xen/kernel/ioport.c
- 3e5a4e653U6cELGv528IxOLHvCq8iA linux-2.4.29-xen-sparse/arch/xen/kernel/irq.c
- 3e5a4e65muT6SU3ck47IP87Q7Ti5hA linux-2.4.29-xen-sparse/arch/xen/kernel/ldt.c
+4270e964iKFC24KiVm6jC5Eo7MxV6w linux-2.4.29-xen-sparse/arch/xen/kernel/pci-dma.c
- 4051db95N9N99FjsRwi49YKUNHWI8A linux-2.4.29-xen-sparse/arch/xen/kernel/pci-pc.c
- 3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ linux-2.4.29-xen-sparse/arch/xen/kernel/process.c
- 3e5a4e66tR-qJMLj3MppcKqmvuI2XQ linux-2.4.29-xen-sparse/arch/xen/kernel/setup.c
- 3e5a4e66fWSTagLGU2P8BGFGRjhDiw linux-2.4.29-xen-sparse/arch/xen/kernel/signal.c
- 3e5a4e66N__lUXNwzQ-eADRzK9LXuQ linux-2.4.29-xen-sparse/arch/xen/kernel/time.c
- 3e5a4e66aHCbQ_F5QZ8VeyikLmuRZQ linux-2.4.29-xen-sparse/arch/xen/kernel/traps.c
- 3e5a4e66-9_NczrVMbuQkoSLyXckIw linux-2.4.29-xen-sparse/arch/xen/lib/Makefile
- 3e5a4e6637ZDk0BvFEC-aFQs599-ng linux-2.4.29-xen-sparse/arch/xen/lib/delay.c
- 3e5a4e66croVgpcJyJuF2ycQw0HuJw linux-2.4.29-xen-sparse/arch/xen/mm/Makefile
- 3e5a4e66l8Q5Tv-6B3lQIRmaVbFPzg linux-2.4.29-xen-sparse/arch/xen/mm/fault.c
- 3e5a4e661gLzzff25pJooKIIWe7IWg linux-2.4.29-xen-sparse/arch/xen/mm/init.c
- 3f0bed43UUdQichXAiVNrjV-y2Kzcg linux-2.4.29-xen-sparse/arch/xen/mm/ioremap.c
- 3e5a4e66qRlSTcjafidMB6ulECADvg linux-2.4.29-xen-sparse/arch/xen/vmlinux.lds
- 3e5a4e66mrtlmV75L1tjKDg8RaM5gA linux-2.4.29-xen-sparse/drivers/block/ll_rw_blk.c
- 40d70c24-Dy2HUMrwSZagfXvAPnI4w linux-2.4.29-xen-sparse/drivers/char/Makefile
- 3f108aeaLcGDgQdFAANLTUEid0a05w linux-2.4.29-xen-sparse/drivers/char/mem.c
- 3e5a4e66rw65CxyolW9PKz4GG42RcA linux-2.4.29-xen-sparse/drivers/char/tty_io.c
- 40c9c0c1pPwYE3-4i-oI3ubUu7UgvQ linux-2.4.29-xen-sparse/drivers/scsi/aic7xxx/Makefile
+41f97f64nW0wmgLxhwzPTzkF4E5ERA linux-2.4.29-xen-sparse/drivers/usb/hcd.c
- 3e5a4e66wbeCpsJgVf_U8Jde-CNcsA linux-2.4.29-xen-sparse/include/asm-xen/bugs.h
- 3e5a4e66HdSkvIV6SJ1evG_xmTmXHA linux-2.4.29-xen-sparse/include/asm-xen/desc.h
- 3e5a4e66SYp_UpAVcF8Lc1wa3Qtgzw linux-2.4.29-xen-sparse/include/asm-xen/fixmap.h
- 406aeeaaQvl4RNtmd9hDEugBURbFpQ linux-2.4.29-xen-sparse/include/asm-xen/highmem.h
- 3e5a4e67YtcyDLQsShhCfQwPSELfvA linux-2.4.29-xen-sparse/include/asm-xen/hw_irq.h
- 4060044fVx7-tokvNLKBf_6qBB4lqQ linux-2.4.29-xen-sparse/include/asm-xen/io.h
- 3e5a4e673p7PEOyHFm3nHkYX6HQYBg linux-2.4.29-xen-sparse/include/asm-xen/irq.h
- 40d70c240tW7TWArl1VUgIFH2nVO1A linux-2.4.29-xen-sparse/include/asm-xen/keyboard.h
- 3e5a4e678ddsQOpbSiRdy1GRcDc9WA linux-2.4.29-xen-sparse/include/asm-xen/mmu_context.h
- 40d06e5b2YWInUX1Xv9amVANwd_2Xg linux-2.4.29-xen-sparse/include/asm-xen/module.h
- 3e5a4e67mnQfh-R8KcQCaVo2Oho6yg linux-2.4.29-xen-sparse/include/asm-xen/page.h
- 409ba2e7ZfV5hqTvIzxLtpClnxtIzg linux-2.4.29-xen-sparse/include/asm-xen/pci.h
- 3e5a4e67uTYU5oEnIDjxuaez8njjqg linux-2.4.29-xen-sparse/include/asm-xen/pgalloc.h
- 3e5a4e67X7JyupgdYkgDX19Huj2sAw linux-2.4.29-xen-sparse/include/asm-xen/pgtable-2level.h
- 3e5a4e67gr4NLGtQ5CvSLimMYZlkOA linux-2.4.29-xen-sparse/include/asm-xen/pgtable.h
- 3e5a4e676uK4xErTBDH6XJREn9LSyg linux-2.4.29-xen-sparse/include/asm-xen/processor.h
- 41224663YBCUMX1kVo_HRUtgaHTi7w linux-2.4.29-xen-sparse/include/asm-xen/queues.h
- 3e5a4e68uJz-xI0IBVMD7xRLQKJDFg linux-2.4.29-xen-sparse/include/asm-xen/segment.h
- 3e5a4e68Nfdh6QcOKUTGCaYkf2LmYA linux-2.4.29-xen-sparse/include/asm-xen/smp.h
- 3e5a4e68mTr0zcp9SXDbnd-XLrrfxw linux-2.4.29-xen-sparse/include/asm-xen/system.h
- 3f1056a9L_kqHcFheV00KbKBzv9j5w linux-2.4.29-xen-sparse/include/asm-xen/vga.h
- 40659defgWA92arexpMGn8X3QMDj3w linux-2.4.29-xen-sparse/include/asm-xen/xor.h
- 3f056927gMHl7mWB89rb73JahbhQIA linux-2.4.29-xen-sparse/include/linux/blk.h
- 42305f54mFScQCttpj57EIm60BnxIg linux-2.4.29-xen-sparse/include/linux/highmem.h
- 419e0488SBzS3mdUhwgsES5a5e3abA linux-2.4.29-xen-sparse/include/linux/irq.h
- 4124f66fPHG6yvB_vXmesjvzrJ3yMg linux-2.4.29-xen-sparse/include/linux/mm.h
- 401c0590D_kwJDU59X8NyvqSv_Cl2A linux-2.4.29-xen-sparse/include/linux/sched.h
- 40a248afgI0_JKthdYAe8beVfXSTpQ linux-2.4.29-xen-sparse/include/linux/skbuff.h
- 401c0592pLrp_aCbQRo9GXiYQQaVVA linux-2.4.29-xen-sparse/include/linux/timer.h
- 3f9d4b44247udoqWEgFkaHiWv6Uvyg linux-2.4.29-xen-sparse/kernel/time.c
- 401c059bjLBFYHRD4Py2uM3eA1D4zQ linux-2.4.29-xen-sparse/kernel/timer.c
- 3e6e7c1efbQe93xCvOpOVCnXTMmQ5w linux-2.4.29-xen-sparse/mkbuildtree
- 406aeeafkrnCuIVWLFv3kfn4uAD5Eg linux-2.4.29-xen-sparse/mm/highmem.c
- 3e5a4e68GxCIaFH4sy01v1wjapetaA linux-2.4.29-xen-sparse/mm/memory.c
- 3f108af5VxPkLv13tXpXgoRKALQtXQ linux-2.4.29-xen-sparse/mm/mprotect.c
- 3e5a4e681xMPdF9xCMwpyfuYMySU5g linux-2.4.29-xen-sparse/mm/mremap.c
- 409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4.29-xen-sparse/mm/page_alloc.c
- 41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.29-xen-sparse/net/core/skbuff.c
+ 3e5a4e6589G-U42lFKs43plskXoFxQ linux-2.4.30-xen-sparse/Makefile
+ 3e5a4e65IEPjnWPZ5w3TxS5scV8Ewg linux-2.4.30-xen-sparse/arch/xen/Makefile
+ 3e5a4e65n-KhsEAs-A4ULiStBp-r6w linux-2.4.30-xen-sparse/arch/xen/boot/Makefile
+ 3e5a4e65OV_j_DBtjzt5vej771AJsA linux-2.4.30-xen-sparse/arch/xen/config.in
+ 40648526SxcA4lGIHB_k7ID8VlRSzw linux-2.4.30-xen-sparse/arch/xen/defconfig-xen0
+ 40c73c77QesbL7eIvG-fJGAtVwhGRg linux-2.4.30-xen-sparse/arch/xen/defconfig-xenU
+ 3e6377f5xwPfYZkPHPrDbEq1PRN7uQ linux-2.4.30-xen-sparse/arch/xen/drivers/balloon/Makefile
+ 4083dc16z0jvZEH4PiVDbDRreaNp6w linux-2.4.30-xen-sparse/arch/xen/drivers/blkif/Makefile
+ 4083dc16KQus88a4U3uCV6qVCA6_8Q linux-2.4.30-xen-sparse/arch/xen/drivers/blkif/backend/Makefile
+ 4075806dI5kfeMD5RV-DA0PYoThx_w linux-2.4.30-xen-sparse/arch/xen/drivers/blkif/frontend/Makefile
+ 4075806d4-j7vN0Mn0bklI1cRUX1vQ linux-2.4.30-xen-sparse/arch/xen/drivers/blkif/frontend/common.h
+ 4075806dibjCcfuXv6CINMhxWTw3jQ linux-2.4.30-xen-sparse/arch/xen/drivers/blkif/frontend/vbd.c
+ 3e5a4e65G3e2s0ghPMgiJ-gBTUJ0uQ linux-2.4.30-xen-sparse/arch/xen/drivers/console/Makefile
+ 3e5a4e656nfFISThfbyXQOA6HN6YHw linux-2.4.30-xen-sparse/arch/xen/drivers/dom0/Makefile
+ 40420a6ebRqDjufoN1WSJvolEW2Wjw linux-2.4.30-xen-sparse/arch/xen/drivers/evtchn/Makefile
+ 4083dc16-Kd5y9psK_yk161sme5j5Q linux-2.4.30-xen-sparse/arch/xen/drivers/netif/Makefile
+ 4083dc16UmHXxS9g_UFVnkUpN-oP2Q linux-2.4.30-xen-sparse/arch/xen/drivers/netif/backend/Makefile
+ 405853f2wg7JXZJNltspMwOZJklxgw linux-2.4.30-xen-sparse/arch/xen/drivers/netif/frontend/Makefile
+ 3e5a4e65lWzkiPXsZdzPt2RNnJGG1g linux-2.4.30-xen-sparse/arch/xen/kernel/Makefile
+ 3e5a4e65_hqfuxtGG8IUy6wRM86Ecg linux-2.4.30-xen-sparse/arch/xen/kernel/entry.S
+ 3e5a4e65Hy_1iUvMTPsNqGNXd9uFpg linux-2.4.30-xen-sparse/arch/xen/kernel/head.S
+ 3e5a4e65RMGcuA-HCn3-wNx3fFQwdg linux-2.4.30-xen-sparse/arch/xen/kernel/i386_ksyms.c
+ 3e5a4e653U6cELGv528IxOLHvCq8iA linux-2.4.30-xen-sparse/arch/xen/kernel/irq.c
+ 3e5a4e65muT6SU3ck47IP87Q7Ti5hA linux-2.4.30-xen-sparse/arch/xen/kernel/ldt.c
+ 4051db95N9N99FjsRwi49YKUNHWI8A linux-2.4.30-xen-sparse/arch/xen/kernel/pci-pc.c
+ 3e5a4e65IGt3WwQDNiL4h-gYWgNTWQ linux-2.4.30-xen-sparse/arch/xen/kernel/process.c
+ 3e5a4e66tR-qJMLj3MppcKqmvuI2XQ linux-2.4.30-xen-sparse/arch/xen/kernel/setup.c
+ 3e5a4e66fWSTagLGU2P8BGFGRjhDiw linux-2.4.30-xen-sparse/arch/xen/kernel/signal.c
+ 3e5a4e66N__lUXNwzQ-eADRzK9LXuQ linux-2.4.30-xen-sparse/arch/xen/kernel/time.c
+ 3e5a4e66aHCbQ_F5QZ8VeyikLmuRZQ linux-2.4.30-xen-sparse/arch/xen/kernel/traps.c
+ 3e5a4e66-9_NczrVMbuQkoSLyXckIw linux-2.4.30-xen-sparse/arch/xen/lib/Makefile
+ 3e5a4e6637ZDk0BvFEC-aFQs599-ng linux-2.4.30-xen-sparse/arch/xen/lib/delay.c
+ 3e5a4e66croVgpcJyJuF2ycQw0HuJw linux-2.4.30-xen-sparse/arch/xen/mm/Makefile
+ 3e5a4e66l8Q5Tv-6B3lQIRmaVbFPzg linux-2.4.30-xen-sparse/arch/xen/mm/fault.c
+ 3e5a4e661gLzzff25pJooKIIWe7IWg linux-2.4.30-xen-sparse/arch/xen/mm/init.c
+ 3f0bed43UUdQichXAiVNrjV-y2Kzcg linux-2.4.30-xen-sparse/arch/xen/mm/ioremap.c
+ 3e5a4e66qRlSTcjafidMB6ulECADvg linux-2.4.30-xen-sparse/arch/xen/vmlinux.lds
+ 3e5a4e66mrtlmV75L1tjKDg8RaM5gA linux-2.4.30-xen-sparse/drivers/block/ll_rw_blk.c
+ 40d70c24-Dy2HUMrwSZagfXvAPnI4w linux-2.4.30-xen-sparse/drivers/char/Makefile
+ 3f108aeaLcGDgQdFAANLTUEid0a05w linux-2.4.30-xen-sparse/drivers/char/mem.c
+ 3e5a4e66rw65CxyolW9PKz4GG42RcA linux-2.4.30-xen-sparse/drivers/char/tty_io.c
+ 40c9c0c1pPwYE3-4i-oI3ubUu7UgvQ linux-2.4.30-xen-sparse/drivers/scsi/aic7xxx/Makefile
-3e5a4e669uzIE54VwucPYtGwXLAbzA linux-2.4.30-xen-sparse/fs/exec.c
+ 3e5a4e66wbeCpsJgVf_U8Jde-CNcsA linux-2.4.30-xen-sparse/include/asm-xen/bugs.h
+ 3e5a4e66HdSkvIV6SJ1evG_xmTmXHA linux-2.4.30-xen-sparse/include/asm-xen/desc.h
+ 3e5a4e66SYp_UpAVcF8Lc1wa3Qtgzw linux-2.4.30-xen-sparse/include/asm-xen/fixmap.h
+ 406aeeaaQvl4RNtmd9hDEugBURbFpQ linux-2.4.30-xen-sparse/include/asm-xen/highmem.h
+ 3e5a4e67YtcyDLQsShhCfQwPSELfvA linux-2.4.30-xen-sparse/include/asm-xen/hw_irq.h
+ 4060044fVx7-tokvNLKBf_6qBB4lqQ linux-2.4.30-xen-sparse/include/asm-xen/io.h
+ 3e5a4e673p7PEOyHFm3nHkYX6HQYBg linux-2.4.30-xen-sparse/include/asm-xen/irq.h
+ 40d70c240tW7TWArl1VUgIFH2nVO1A linux-2.4.30-xen-sparse/include/asm-xen/keyboard.h
+ 3e5a4e678ddsQOpbSiRdy1GRcDc9WA linux-2.4.30-xen-sparse/include/asm-xen/mmu_context.h
+ 40d06e5b2YWInUX1Xv9amVANwd_2Xg linux-2.4.30-xen-sparse/include/asm-xen/module.h
-3f8707e7ZmZ6TxyX0ZUEfvhA2Pb_xQ linux-2.4.30-xen-sparse/include/asm-xen/msr.h
+ 3e5a4e67mnQfh-R8KcQCaVo2Oho6yg linux-2.4.30-xen-sparse/include/asm-xen/page.h
+ 409ba2e7ZfV5hqTvIzxLtpClnxtIzg linux-2.4.30-xen-sparse/include/asm-xen/pci.h
+ 3e5a4e67uTYU5oEnIDjxuaez8njjqg linux-2.4.30-xen-sparse/include/asm-xen/pgalloc.h
+ 3e5a4e67X7JyupgdYkgDX19Huj2sAw linux-2.4.30-xen-sparse/include/asm-xen/pgtable-2level.h
+ 3e5a4e67gr4NLGtQ5CvSLimMYZlkOA linux-2.4.30-xen-sparse/include/asm-xen/pgtable.h
+ 3e5a4e676uK4xErTBDH6XJREn9LSyg linux-2.4.30-xen-sparse/include/asm-xen/processor.h
+ 41224663YBCUMX1kVo_HRUtgaHTi7w linux-2.4.30-xen-sparse/include/asm-xen/queues.h
+ 3e5a4e68uJz-xI0IBVMD7xRLQKJDFg linux-2.4.30-xen-sparse/include/asm-xen/segment.h
+ 3e5a4e68Nfdh6QcOKUTGCaYkf2LmYA linux-2.4.30-xen-sparse/include/asm-xen/smp.h
+ 3e5a4e68mTr0zcp9SXDbnd-XLrrfxw linux-2.4.30-xen-sparse/include/asm-xen/system.h
+ 3f1056a9L_kqHcFheV00KbKBzv9j5w linux-2.4.30-xen-sparse/include/asm-xen/vga.h
+ 40659defgWA92arexpMGn8X3QMDj3w linux-2.4.30-xen-sparse/include/asm-xen/xor.h
+ 3f056927gMHl7mWB89rb73JahbhQIA linux-2.4.30-xen-sparse/include/linux/blk.h
+ 42305f54mFScQCttpj57EIm60BnxIg linux-2.4.30-xen-sparse/include/linux/highmem.h
+ 419e0488SBzS3mdUhwgsES5a5e3abA linux-2.4.30-xen-sparse/include/linux/irq.h
+ 4124f66fPHG6yvB_vXmesjvzrJ3yMg linux-2.4.30-xen-sparse/include/linux/mm.h
+ 401c0590D_kwJDU59X8NyvqSv_Cl2A linux-2.4.30-xen-sparse/include/linux/sched.h
+ 40a248afgI0_JKthdYAe8beVfXSTpQ linux-2.4.30-xen-sparse/include/linux/skbuff.h
+ 401c0592pLrp_aCbQRo9GXiYQQaVVA linux-2.4.30-xen-sparse/include/linux/timer.h
+ 3f9d4b44247udoqWEgFkaHiWv6Uvyg linux-2.4.30-xen-sparse/kernel/time.c
+ 401c059bjLBFYHRD4Py2uM3eA1D4zQ linux-2.4.30-xen-sparse/kernel/timer.c
+ 3e6e7c1efbQe93xCvOpOVCnXTMmQ5w linux-2.4.30-xen-sparse/mkbuildtree
+ 406aeeafkrnCuIVWLFv3kfn4uAD5Eg linux-2.4.30-xen-sparse/mm/highmem.c
+ 3e5a4e68GxCIaFH4sy01v1wjapetaA linux-2.4.30-xen-sparse/mm/memory.c
+ 3f108af5VxPkLv13tXpXgoRKALQtXQ linux-2.4.30-xen-sparse/mm/mprotect.c
+ 3e5a4e681xMPdF9xCMwpyfuYMySU5g linux-2.4.30-xen-sparse/mm/mremap.c
+ 409ba2e7akOFqQUg6Qyg2s28xcXiMg linux-2.4.30-xen-sparse/mm/page_alloc.c
-3e5a4e683HKVU-sxtagrDasRB8eBVw linux-2.4.30-xen-sparse/mm/swapfile.c
-41180721bNns9Na7w1nJ0ZVt8bhUNA linux-2.4.30-xen-sparse/mm/vmalloc.c
+ 41505c57WAd5l1rlfCLNSCpx9J13vA linux-2.4.30-xen-sparse/net/core/skbuff.c
40f562372u3A7_kfbYYixPHJJxYUxA linux-2.6.11-xen-sparse/arch/xen/Kconfig
40f56237utH41NPukqHksuNf29IC9A linux-2.6.11-xen-sparse/arch/xen/Kconfig.drivers
40f56237penAAlWVBVDpeQZNFIg8CA linux-2.6.11-xen-sparse/arch/xen/Makefile
--- /dev/null
+ #
+ # xen/Makefile
+ #
+ # This file is included by the global makefile so that you can add your own
+ # architecture-specific flags and dependencies. Remember to do have actions
+ # for "archclean" and "archdep" for cleaning up and making dependencies for
+ # this architecture
+ #
+ # This file is subject to the terms and conditions of the GNU General Public
+ # License. See the file "COPYING" in the main directory of this archive
+ # for more details.
+ #
+ # Copyright (C) 1994 by Linus Torvalds
+ #
+ # 19990713 Artur Skawina <skawina@geocities.com>
+ # Added '-march' and '-mpreferred-stack-boundary' support
+ #
+
+ # If no .config file exists then use the appropriate defconfig-* file
+ ifneq (.config,$(wildcard .config))
+ DUMMYX:=$(shell cp $(TOPDIR)/arch/xen/defconfig$(EXTRAVERSION) $(TOPDIR)/.config)
+ -include $(TOPDIR)/.config
+ endif
+
+ LD=$(CROSS_COMPILE)ld -m elf_i386
+ OBJCOPY=$(CROSS_COMPILE)objcopy -R .note -R .comment -S
+ LDFLAGS=-e stext
+ LINKFLAGS =-T $(TOPDIR)/arch/xen/vmlinux.lds $(LDFLAGS)
+
+ CFLAGS += -pipe
+
+ check_gcc = $(shell if $(CC) $(1) -S -o /dev/null -xc /dev/null > /dev/null 2>&1; then echo "$(1)"; else echo "$(2)"; fi)
+
+ # prevent gcc from keeping the stack 16 byte aligned
+ CFLAGS += $(call check_gcc,-mpreferred-stack-boundary=2,)
+
+ ifdef CONFIG_M686
+ CFLAGS += -march=i686
+ endif
+
+ ifdef CONFIG_MPENTIUMIII
+ CFLAGS += -march=i686
+ endif
+
+ ifdef CONFIG_MPENTIUM4
+ CFLAGS += -march=i686
+ endif
+
+ ifdef CONFIG_MK7
+ CFLAGS += $(call check_gcc,-march=athlon,-march=i686 -malign-functions=4)
+ endif
+
+ # Disable unit-at-a-time mode, it makes gcc use a lot more stack
+ # due to the lack of sharing of stacklots.
+ CFLAGS += $(call check_gcc,-fno-unit-at-a-time,)
+
+ HEAD := arch/xen/kernel/head.o arch/xen/kernel/init_task.o
+
+ SUBDIRS += arch/xen/kernel arch/xen/mm arch/xen/lib
+ SUBDIRS += arch/xen/drivers/console
+ SUBDIRS += arch/xen/drivers/evtchn
+ SUBDIRS += arch/xen/drivers/blkif
+ SUBDIRS += arch/xen/drivers/netif
++SUBDIRS += arch/xen/drivers/usbif
+ SUBDIRS += arch/xen/drivers/balloon
+ ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ SUBDIRS += arch/xen/drivers/dom0
+ endif
+
+ CORE_FILES += arch/xen/kernel/kernel.o arch/xen/mm/mm.o
+ CORE_FILES += arch/xen/drivers/evtchn/drv.o
+ CORE_FILES += arch/xen/drivers/console/drv.o
+ DRIVERS += arch/xen/drivers/blkif/drv.o
+ DRIVERS += arch/xen/drivers/netif/drv.o
++DRIVERS += arch/xen/drivers/usbif/drv.o
+ ifdef CONFIG_XEN_PRIVILEGED_GUEST
+ CORE_FILES += arch/xen/drivers/dom0/drv.o
+ endif
+ CORE_FILES += arch/xen/drivers/balloon/drv.o
+ LIBS := $(TOPDIR)/arch/xen/lib/lib.a $(LIBS) $(TOPDIR)/arch/xen/lib/lib.a
+
+ arch/xen/kernel: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/xen/kernel
+
+ arch/xen/mm: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/xen/mm
+
+ arch/xen/drivers/console: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/xen/drivers/console
+
+ arch/xen/drivers/network: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/xen/drivers/network
+
+ arch/xen/drivers/block: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/xen/drivers/block
+
+ arch/xen/drivers/dom0: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/xen/drivers/dom0
+
+ arch/xen/drivers/balloon: dummy
+ $(MAKE) linuxsubdirs SUBDIRS=arch/xen/drivers/balloon
+
+ MAKEBOOT = $(MAKE) -C arch/$(ARCH)/boot
+
+ vmlinux: arch/xen/vmlinux.lds
+
+ FORCE: ;
+
+ .PHONY: bzImage compressed clean archclean archmrproper archdep
+
+
+ bzImage: vmlinux
+ @$(MAKEBOOT) bzImage
+
+ INSTALL_NAME ?= $(KERNELRELEASE)
+ install: bzImage
+ mkdir -p $(INSTALL_PATH)/boot
+ ln -f -s vmlinuz-$(INSTALL_NAME)$(INSTALL_SUFFIX) $(INSTALL_PATH)/boot/vmlinuz-$(VERSION).$(PATCHLEVEL).$(SUBLEVEL)$(XENGUEST)$(INSTALL_SUFFIX)
+ rm -f $(INSTALL_PATH)/boot/vmlinuz-$(INSTALL_NAME)$(INSTALL_SUFFIX)
+ install -m0644 arch/$(ARCH)/boot/bzImage $(INSTALL_PATH)/boot/vmlinuz-$(INSTALL_NAME)$(INSTALL_SUFFIX)
+ install -m0644 vmlinux $(INSTALL_PATH)/boot/vmlinux-syms-$(INSTALL_NAME)$(INSTALL_SUFFIX)
+ install -m0664 .config $(INSTALL_PATH)/boot/config-$(INSTALL_NAME)$(INSTALL_SUFFIX)
+ install -m0664 System.map $(INSTALL_PATH)/boot/System.map-$(INSTALL_NAME)$(INSTALL_SUFFIX)
+ ln -f -s vmlinuz-$(INSTALL_NAME)$(INSTALL_SUFFIX) $(INSTALL_PATH)/boot/vmlinuz-$(VERSION).$(PATCHLEVEL)$(XENGUEST)$(INSTALL_SUFFIX)
+
+ %_config: arch/xen/defconfig-%
+ rm -f .config arch/xen/defconfig
+ cp -f arch/xen/defconfig-$(@:_config=) arch/xen/defconfig
+ cp -f arch/xen/defconfig-$(@:_config=) .config
+
+
+ archclean:
+ @$(MAKEBOOT) clean
+
+ archmrproper:
+ rm -f include/asm-xen/xen-public/arch
+
+ archdep:
+ @$(MAKEBOOT) dep
--- /dev/null
-if [ "$CONFIG_XEN_PHYSDEV_ACCESS" == "y" ]; then
+ #
+ # For a description of the syntax of this configuration file,
+ # see Documentation/kbuild/config-language.txt.
+ #
+ mainmenu_name "Linux Kernel Configuration"
+
+ define_bool CONFIG_XEN y
+
+ define_bool CONFIG_X86 y
+ define_bool CONFIG_ISA y
+ define_bool CONFIG_SBUS n
+
+ define_bool CONFIG_UID16 y
+
+ mainmenu_option next_comment
+ comment 'Xen'
+ bool 'Support for privileged operations (domain 0)' CONFIG_XEN_PRIVILEGED_GUEST
+ bool 'Device-driver domain (physical device access)' CONFIG_XEN_PHYSDEV_ACCESS
++if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
++ bool 'USB-device backend driver' CONFIG_XEN_USB_BACKEND
++fi
+ bool 'Scrub memory before freeing it to Xen' CONFIG_XEN_SCRUB_PAGES
+ bool 'Network-device frontend driver' CONFIG_XEN_NETDEV_FRONTEND
+ bool 'Block-device frontend driver' CONFIG_XEN_BLKDEV_FRONTEND
++bool 'Block-device uses grant tables' CONFIG_XEN_BLKDEV_GRANT
++bool 'USB-device frontend driver' CONFIG_XEN_USB_FRONTEND
+ endmenu
+ # The IBM S/390 patch needs this.
+ define_bool CONFIG_NO_IDLE_HZ y
+
-if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
++if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ define_bool CONFIG_FOREIGN_PAGES y
+ else
+ define_bool CONFIG_FOREIGN_PAGES n
+ define_bool CONFIG_NETDEVICES y
+ define_bool CONFIG_VT n
+ fi
+
+ mainmenu_option next_comment
+ comment 'Code maturity level options'
+ bool 'Prompt for development and/or incomplete code/drivers' CONFIG_EXPERIMENTAL
+ endmenu
+
+ mainmenu_option next_comment
+ comment 'Loadable module support'
+ bool 'Enable loadable module support' CONFIG_MODULES
+ if [ "$CONFIG_MODULES" = "y" ]; then
+ bool ' Set version information on all module symbols' CONFIG_MODVERSIONS
+ bool ' Kernel module loader' CONFIG_KMOD
+ fi
+ endmenu
+
+ mainmenu_option next_comment
+ comment 'Processor type and features'
+ choice 'Processor family' \
+ "Pentium-Pro/Celeron/Pentium-II CONFIG_M686 \
+ Pentium-III/Celeron(Coppermine) CONFIG_MPENTIUMIII \
+ Pentium-4 CONFIG_MPENTIUM4 \
+ Athlon/Duron/K7 CONFIG_MK7 \
+ Opteron/Athlon64/Hammer/K8 CONFIG_MK8 \
+ VIA-C3-2 CONFIG_MVIAC3_2" Pentium-Pro
+
+ define_bool CONFIG_X86_WP_WORKS_OK y
+ define_bool CONFIG_X86_INVLPG y
+ define_bool CONFIG_X86_CMPXCHG y
+ define_bool CONFIG_X86_XADD y
+ define_bool CONFIG_X86_BSWAP y
+ define_bool CONFIG_X86_POPAD_OK y
+ define_bool CONFIG_RWSEM_GENERIC_SPINLOCK n
+ define_bool CONFIG_RWSEM_XCHGADD_ALGORITHM y
+
+ define_bool CONFIG_X86_GOOD_APIC y
+ define_bool CONFIG_X86_PGE y
+ define_bool CONFIG_X86_USE_PPRO_CHECKSUM y
+ define_bool CONFIG_X86_TSC y
+
+ if [ "$CONFIG_M686" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_SHIFT 5
+ fi
+ if [ "$CONFIG_MPENTIUMIII" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_SHIFT 5
+ fi
+ if [ "$CONFIG_MPENTIUM4" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_SHIFT 7
+ fi
+ if [ "$CONFIG_MK8" = "y" ]; then
+ define_bool CONFIG_MK7 y
+ fi
+ if [ "$CONFIG_MK7" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_SHIFT 6
+ define_bool CONFIG_X86_USE_3DNOW y
+ fi
+ if [ "$CONFIG_MVIAC3_2" = "y" ]; then
+ define_int CONFIG_X86_L1_CACHE_SHIFT 5
+ fi
+
+ #if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ # tristate 'BIOS Enhanced Disk Drive calls determine boot disk (EXPERIMENTAL)' CONFIG_EDD
+ #fi
+
+ choice 'High Memory Support' \
+ "off CONFIG_NOHIGHMEM \
+ 4GB CONFIG_HIGHMEM4G" off
+ # 64GB CONFIG_HIGHMEM64G" off
+ if [ "$CONFIG_HIGHMEM4G" = "y" ]; then
+ define_bool CONFIG_HIGHMEM y
+ fi
+ if [ "$CONFIG_HIGHMEM64G" = "y" ]; then
+ define_bool CONFIG_HIGHMEM y
+ define_bool CONFIG_X86_PAE y
+ fi
+
+ if [ "$CONFIG_HIGHMEM" = "y" ]; then
+ bool 'HIGHMEM I/O support' CONFIG_HIGHIO
+ fi
+
+ define_int CONFIG_FORCE_MAX_ZONEORDER 11
+
+ #bool 'Symmetric multi-processing support' CONFIG_SMP
+ #if [ "$CONFIG_SMP" = "y" -a "$CONFIG_X86_CMPXCHG" = "y" ]; then
+ # define_bool CONFIG_HAVE_DEC_LOCK y
+ #fi
+ endmenu
+
+ mainmenu_option next_comment
+ comment 'General setup'
+
+ bool 'Networking support' CONFIG_NET
+
+ if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ bool 'PCI support' CONFIG_PCI
+ source drivers/pci/Config.in
+
+ bool 'Support for hot-pluggable devices' CONFIG_HOTPLUG
+
+ if [ "$CONFIG_HOTPLUG" = "y" ] ; then
+ source drivers/pcmcia/Config.in
+ source drivers/hotplug/Config.in
+ else
+ define_bool CONFIG_PCMCIA n
+ define_bool CONFIG_HOTPLUG_PCI n
+ fi
+ fi
+
+ bool 'System V IPC' CONFIG_SYSVIPC
+ bool 'BSD Process Accounting' CONFIG_BSD_PROCESS_ACCT
+ bool 'Sysctl support' CONFIG_SYSCTL
+ if [ "$CONFIG_PROC_FS" = "y" ]; then
+ choice 'Kernel core (/proc/kcore) format' \
+ "ELF CONFIG_KCORE_ELF \
+ A.OUT CONFIG_KCORE_AOUT" ELF
+ fi
+ tristate 'Kernel support for a.out binaries' CONFIG_BINFMT_AOUT
+ bool 'Kernel support for ELF binaries' CONFIG_BINFMT_ELF
+ tristate 'Kernel support for MISC binaries' CONFIG_BINFMT_MISC
+ bool 'Select task to kill on out of memory condition' CONFIG_OOM_KILLER
+
+ endmenu
+
+ if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ source drivers/mtd/Config.in
+
+ source drivers/parport/Config.in
+
+ source drivers/pnp/Config.in
+
+ source drivers/block/Config.in
+
+ source drivers/md/Config.in
+ fi
+
+ if [ "$CONFIG_NET" = "y" ]; then
+ source net/Config.in
+ fi
+
+ if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'ATA/IDE/MFM/RLL support'
+
+ tristate 'ATA/IDE/MFM/RLL support' CONFIG_IDE
+
+ if [ "$CONFIG_IDE" != "n" ]; then
+ source drivers/ide/Config.in
+ else
+ define_bool CONFIG_BLK_DEV_HD n
+ fi
+ endmenu
+ fi
+
+ mainmenu_option next_comment
+ comment 'SCSI support'
+
+ tristate 'SCSI support' CONFIG_SCSI
+
+ if [ "$CONFIG_SCSI" != "n" ]; then
+ source drivers/scsi/Config.in
+ fi
+ endmenu
+
+ if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ source drivers/message/fusion/Config.in
+
+ source drivers/ieee1394/Config.in
+
+ source drivers/message/i2o/Config.in
+
+ if [ "$CONFIG_NET" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Network device support'
+
+ bool 'Network device support' CONFIG_NETDEVICES
+ if [ "$CONFIG_NETDEVICES" = "y" ]; then
+ source drivers/net/Config.in
+ if [ "$CONFIG_ATM" = "y" -o "$CONFIG_ATM" = "m" ]; then
+ source drivers/atm/Config.in
+ fi
+ fi
+ endmenu
+ fi
+
+ source net/ax25/Config.in
+
+ source net/irda/Config.in
+
+ mainmenu_option next_comment
+ comment 'ISDN subsystem'
+ if [ "$CONFIG_NET" != "n" ]; then
+ tristate 'ISDN support' CONFIG_ISDN
+ if [ "$CONFIG_ISDN" != "n" ]; then
+ source drivers/isdn/Config.in
+ fi
+ fi
+ endmenu
+
+ if [ "$CONFIG_ISA" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Old CD-ROM drivers (not SCSI, not IDE)'
+
+ bool 'Support non-SCSI/IDE/ATAPI CDROM drives' CONFIG_CD_NO_IDESCSI
+ if [ "$CONFIG_CD_NO_IDESCSI" != "n" ]; then
+ source drivers/cdrom/Config.in
+ fi
+ endmenu
+ fi
+
+ #
+ # input before char - char/joystick depends on it. As does USB.
+ #
+ source drivers/input/Config.in
+ else
+ #
+ # Block device driver configuration
+ #
+ mainmenu_option next_comment
+ comment 'Block devices'
+ tristate 'Loopback device support' CONFIG_BLK_DEV_LOOP
+ dep_tristate 'Network block device support' CONFIG_BLK_DEV_NBD $CONFIG_NET
+ tristate 'RAM disk support' CONFIG_BLK_DEV_RAM
+ if [ "$CONFIG_BLK_DEV_RAM" = "y" -o "$CONFIG_BLK_DEV_RAM" = "m" ]; then
+ int ' Default RAM disk size' CONFIG_BLK_DEV_RAM_SIZE 4096
+ fi
+ dep_bool ' Initial RAM disk (initrd) support' CONFIG_BLK_DEV_INITRD $CONFIG_BLK_DEV_RAM
+ bool 'Per partition statistics in /proc/partitions' CONFIG_BLK_STATS
+ define_bool CONFIG_BLK_DEV_HD n
+ endmenu
+ fi
+
+ source drivers/char/Config.in
+
++if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" -o "$CONFIG_XEN_USB_FRONTEND" = "y" ]; then
+ source drivers/media/Config.in
+ fi
+
+ source fs/Config.in
+
+ mainmenu_option next_comment
+ comment 'Console drivers'
+
+ define_bool CONFIG_XEN_CONSOLE y
+
+ if [ "$CONFIG_VT" = "y" ]; then
+ bool 'VGA text console' CONFIG_VGA_CONSOLE
+ bool 'Dummy console' CONFIG_DUMMY_CONSOLE
+ if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ bool 'Video mode selection support' CONFIG_VIDEO_SELECT
+ if [ "$CONFIG_EXPERIMENTAL" = "y" ]; then
+ tristate 'MDA text console (dual-headed) (EXPERIMENTAL)' CONFIG_MDA_CONSOLE
+ source drivers/video/Config.in
+ fi
+ fi
+ fi
+ endmenu
+
+ if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ mainmenu_option next_comment
+ comment 'Sound'
+
+ tristate 'Sound card support' CONFIG_SOUND
+ if [ "$CONFIG_SOUND" != "n" ]; then
+ source drivers/sound/Config.in
+ fi
+ endmenu
++fi
+
++if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" -o "$CONFIG_XEN_USB_FRONTEND" = "y" ]; then
++ if [ "$CONFIG_XEN_USB_FRONTEND" = "y" -o "$CONFIG_XEN_USB_BACKEND" = "y" ]; then
++ define_bool CONFIG_USB y
++ fi
+ source drivers/usb/Config.in
++fi
+
++if [ "$CONFIG_XEN_PHYSDEV_ACCESS" = "y" ]; then
+ source net/bluetooth/Config.in
+ fi
+
+ mainmenu_option next_comment
+ comment 'Kernel hacking'
+
+ bool 'Kernel debugging' CONFIG_DEBUG_KERNEL
+ if [ "$CONFIG_DEBUG_KERNEL" != "n" ]; then
+ bool ' Check for stack overflows' CONFIG_DEBUG_STACKOVERFLOW
+ bool ' Debug high memory support' CONFIG_DEBUG_HIGHMEM
+ bool ' Debug memory allocations' CONFIG_DEBUG_SLAB
+ bool ' Memory mapped I/O debugging' CONFIG_DEBUG_IOVIRT
+ bool ' Magic SysRq key' CONFIG_MAGIC_SYSRQ
+ bool ' Spinlock debugging' CONFIG_DEBUG_SPINLOCK
+ bool ' Verbose BUG() reporting (adds 70K)' CONFIG_DEBUG_BUGVERBOSE
+ bool ' Load all symbols for debugging' CONFIG_KALLSYMS
+ bool ' Compile the kernel with frame pointers' CONFIG_FRAME_POINTER
+ fi
+
+ int 'Kernel messages buffer length shift (0 = default)' CONFIG_LOG_BUF_SHIFT 0
+
+ endmenu
+
+ source crypto/Config.in
+ source lib/Config.in
--- /dev/null
+ #
+ # Automatically generated by make menuconfig: don't edit
+ #
+ CONFIG_XEN=y
+ CONFIG_X86=y
+ CONFIG_ISA=y
+ # CONFIG_SBUS is not set
+ CONFIG_UID16=y
+
+ #
+ # Xen
+ #
+ CONFIG_XEN_PRIVILEGED_GUEST=y
+ CONFIG_XEN_PHYSDEV_ACCESS=y
++# CONFIG_XEN_USB_BACKEND is not set
+ CONFIG_XEN_SCRUB_PAGES=y
+ CONFIG_XEN_NETDEV_FRONTEND=y
+ CONFIG_XEN_BLKDEV_FRONTEND=y
++CONFIG_XEN_BLKDEV_GRANT=y
++# CONFIG_XEN_USB_FRONTEND is not set
+ CONFIG_NO_IDLE_HZ=y
+ CONFIG_FOREIGN_PAGES=y
+
+ #
+ # Code maturity level options
+ #
+ CONFIG_EXPERIMENTAL=y
+
+ #
+ # Loadable module support
+ #
+ CONFIG_MODULES=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_KMOD=y
+
+ #
+ # Processor type and features
+ #
+ CONFIG_M686=y
+ # CONFIG_MPENTIUMIII is not set
+ # CONFIG_MPENTIUM4 is not set
+ # CONFIG_MK7 is not set
+ # CONFIG_MK8 is not set
+ # CONFIG_MVIAC3_2 is not set
+ CONFIG_X86_WP_WORKS_OK=y
+ CONFIG_X86_INVLPG=y
+ CONFIG_X86_CMPXCHG=y
+ CONFIG_X86_XADD=y
+ CONFIG_X86_BSWAP=y
+ CONFIG_X86_POPAD_OK=y
+ # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+ CONFIG_X86_GOOD_APIC=y
+ CONFIG_X86_PGE=y
+ CONFIG_X86_USE_PPRO_CHECKSUM=y
+ CONFIG_X86_TSC=y
+ CONFIG_X86_L1_CACHE_SHIFT=5
+ CONFIG_NOHIGHMEM=y
+ # CONFIG_HIGHMEM4G is not set
+ CONFIG_FORCE_MAX_ZONEORDER=11
+
+ #
+ # General setup
+ #
+ CONFIG_NET=y
+ CONFIG_PCI=y
+ CONFIG_PCI_NAMES=y
+ CONFIG_HOTPLUG=y
+
+ #
+ # PCMCIA/CardBus support
+ #
+ # CONFIG_PCMCIA is not set
+
+ #
+ # PCI Hotplug Support
+ #
+ # CONFIG_HOTPLUG_PCI is not set
+ # CONFIG_HOTPLUG_PCI_COMPAQ is not set
+ # CONFIG_HOTPLUG_PCI_COMPAQ_NVRAM is not set
+ # CONFIG_HOTPLUG_PCI_SHPC is not set
+ # CONFIG_HOTPLUG_PCI_SHPC_POLL_EVENT_MODE is not set
+ # CONFIG_HOTPLUG_PCI_PCIE is not set
+ # CONFIG_HOTPLUG_PCI_PCIE_POLL_EVENT_MODE is not set
+ CONFIG_SYSVIPC=y
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ # CONFIG_KCORE_AOUT is not set
+ CONFIG_BINFMT_AOUT=y
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_MISC is not set
+ # CONFIG_OOM_KILLER is not set
+
+ #
+ # Memory Technology Devices (MTD)
+ #
+ # CONFIG_MTD is not set
+
+ #
+ # Parallel port support
+ #
+ # CONFIG_PARPORT is not set
+
+ #
+ # Plug and Play configuration
+ #
+ CONFIG_PNP=y
+ # CONFIG_ISAPNP is not set
+
+ #
+ # Block devices
+ #
+ # CONFIG_BLK_DEV_FD is not set
+ # CONFIG_BLK_DEV_XD is not set
+ # CONFIG_PARIDE is not set
+ # CONFIG_BLK_CPQ_DA is not set
+ # CONFIG_BLK_CPQ_CISS_DA is not set
+ # CONFIG_CISS_SCSI_TAPE is not set
+ # CONFIG_CISS_MONITOR_THREAD is not set
+ # CONFIG_BLK_DEV_DAC960 is not set
+ # CONFIG_BLK_DEV_UMEM is not set
+ # CONFIG_BLK_DEV_SX8 is not set
+ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_NBD=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+ CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_BLK_STATS is not set
+
+ #
+ # Multi-device support (RAID and LVM)
+ #
+ CONFIG_MD=y
+ CONFIG_BLK_DEV_MD=y
+ CONFIG_MD_LINEAR=y
+ # CONFIG_MD_RAID0 is not set
+ CONFIG_MD_RAID1=y
+ # CONFIG_MD_RAID5 is not set
+ # CONFIG_MD_MULTIPATH is not set
+ CONFIG_BLK_DEV_LVM=y
+
+ #
+ # Networking options
+ #
+ CONFIG_PACKET=y
+ CONFIG_PACKET_MMAP=y
+ # CONFIG_NETLINK_DEV is not set
+ CONFIG_NETFILTER=y
+ # CONFIG_NETFILTER_DEBUG is not set
+ CONFIG_FILTER=y
+ CONFIG_UNIX=y
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+ # CONFIG_IP_ADVANCED_ROUTER is not set
+ CONFIG_IP_PNP=y
+ CONFIG_IP_PNP_DHCP=y
+ # CONFIG_IP_PNP_BOOTP is not set
+ # CONFIG_IP_PNP_RARP is not set
+ # CONFIG_NET_IPIP is not set
+ # CONFIG_NET_IPGRE is not set
+ # CONFIG_ARPD is not set
+ # CONFIG_INET_ECN is not set
+ # CONFIG_SYN_COOKIES is not set
+
+ #
+ # IP: Netfilter Configuration
+ #
+ CONFIG_IP_NF_CONNTRACK=m
+ CONFIG_IP_NF_FTP=m
+ # CONFIG_IP_NF_AMANDA is not set
+ CONFIG_IP_NF_TFTP=m
+ CONFIG_IP_NF_IRC=m
+ # CONFIG_IP_NF_QUEUE is not set
+ CONFIG_IP_NF_IPTABLES=y
+ # CONFIG_IP_NF_MATCH_LIMIT is not set
+ # CONFIG_IP_NF_MATCH_MAC is not set
+ # CONFIG_IP_NF_MATCH_PKTTYPE is not set
+ # CONFIG_IP_NF_MATCH_MARK is not set
+ # CONFIG_IP_NF_MATCH_MULTIPORT is not set
+ # CONFIG_IP_NF_MATCH_TOS is not set
+ # CONFIG_IP_NF_MATCH_RECENT is not set
+ # CONFIG_IP_NF_MATCH_ECN is not set
+ # CONFIG_IP_NF_MATCH_DSCP is not set
+ # CONFIG_IP_NF_MATCH_AH_ESP is not set
+ # CONFIG_IP_NF_MATCH_LENGTH is not set
+ # CONFIG_IP_NF_MATCH_TTL is not set
+ # CONFIG_IP_NF_MATCH_TCPMSS is not set
+ # CONFIG_IP_NF_MATCH_HELPER is not set
+ CONFIG_IP_NF_MATCH_STATE=m
+ CONFIG_IP_NF_MATCH_CONNTRACK=m
+ # CONFIG_IP_NF_MATCH_UNCLEAN is not set
+ # CONFIG_IP_NF_MATCH_OWNER is not set
+ CONFIG_IP_NF_MATCH_PHYSDEV=y
+ CONFIG_IP_NF_FILTER=y
+ CONFIG_IP_NF_TARGET_REJECT=y
+ # CONFIG_IP_NF_TARGET_MIRROR is not set
+ CONFIG_IP_NF_NAT=m
+ CONFIG_IP_NF_NAT_NEEDED=y
+ CONFIG_IP_NF_TARGET_MASQUERADE=m
+ CONFIG_IP_NF_TARGET_REDIRECT=m
+ # CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+ CONFIG_IP_NF_NAT_IRC=m
+ CONFIG_IP_NF_NAT_FTP=m
+ CONFIG_IP_NF_NAT_TFTP=m
+ # CONFIG_IP_NF_MANGLE is not set
+ CONFIG_IP_NF_TARGET_LOG=y
+ CONFIG_IP_NF_TARGET_ULOG=y
+ # CONFIG_IP_NF_TARGET_TCPMSS is not set
+ # CONFIG_IP_NF_ARPTABLES is not set
+
+ #
+ # IP: Virtual Server Configuration
+ #
+ # CONFIG_IP_VS is not set
+ # CONFIG_IPV6 is not set
+ # CONFIG_KHTTPD is not set
+
+ #
+ # SCTP Configuration (EXPERIMENTAL)
+ #
+ # CONFIG_IP_SCTP is not set
+ # CONFIG_ATM is not set
+ CONFIG_VLAN_8021Q=y
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+ # CONFIG_DECNET is not set
+ CONFIG_BRIDGE=y
+ CONFIG_BRIDGE_NF_EBTABLES=m
+ CONFIG_BRIDGE_EBT_T_FILTER=m
+ CONFIG_BRIDGE_EBT_T_NAT=m
+ CONFIG_BRIDGE_EBT_BROUTE=m
+ CONFIG_BRIDGE_EBT_LOG=m
+ CONFIG_BRIDGE_EBT_IPF=m
+ CONFIG_BRIDGE_EBT_ARPF=m
+ CONFIG_BRIDGE_EBT_AMONG=m
+ CONFIG_BRIDGE_EBT_LIMIT=m
+ CONFIG_BRIDGE_EBT_VLANF=m
+ CONFIG_BRIDGE_EBT_802_3=m
+ CONFIG_BRIDGE_EBT_PKTTYPE=m
+ CONFIG_BRIDGE_EBT_STP=m
+ CONFIG_BRIDGE_EBT_MARKF=m
+ CONFIG_BRIDGE_EBT_ARPREPLY=m
+ CONFIG_BRIDGE_EBT_SNAT=m
+ CONFIG_BRIDGE_EBT_DNAT=m
+ CONFIG_BRIDGE_EBT_REDIRECT=m
+ CONFIG_BRIDGE_EBT_MARK_T=m
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+ # CONFIG_LLC is not set
+ # CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+ # CONFIG_NET_FASTROUTE is not set
+ # CONFIG_NET_HW_FLOWCONTROL is not set
+
+ #
+ # QoS and/or fair queueing
+ #
+ # CONFIG_NET_SCHED is not set
+
+ #
+ # Network testing
+ #
+ # CONFIG_NET_PKTGEN is not set
+
+ #
+ # ATA/IDE/MFM/RLL support
+ #
+ CONFIG_IDE=y
+
+ #
+ # IDE, ATA and ATAPI Block devices
+ #
+ CONFIG_BLK_DEV_IDE=y
+ # CONFIG_BLK_DEV_HD_IDE is not set
+ # CONFIG_BLK_DEV_HD is not set
+ # CONFIG_BLK_DEV_IDE_SATA is not set
+ CONFIG_BLK_DEV_IDEDISK=y
+ CONFIG_IDEDISK_MULTI_MODE=y
+ CONFIG_IDEDISK_STROKE=y
+ # CONFIG_BLK_DEV_IDECS is not set
+ # CONFIG_BLK_DEV_DELKIN is not set
+ CONFIG_BLK_DEV_IDECD=y
+ CONFIG_BLK_DEV_IDETAPE=y
+ CONFIG_BLK_DEV_IDEFLOPPY=y
+ CONFIG_BLK_DEV_IDESCSI=y
+ CONFIG_IDE_TASK_IOCTL=y
+ CONFIG_BLK_DEV_CMD640=y
+ CONFIG_BLK_DEV_CMD640_ENHANCED=y
+ # CONFIG_BLK_DEV_ISAPNP is not set
+ CONFIG_BLK_DEV_IDEPCI=y
+ CONFIG_BLK_DEV_GENERIC=y
+ CONFIG_IDEPCI_SHARE_IRQ=y
+ CONFIG_BLK_DEV_IDEDMA_PCI=y
+ CONFIG_BLK_DEV_OFFBOARD=y
+ # CONFIG_BLK_DEV_IDEDMA_FORCED is not set
+ CONFIG_IDEDMA_PCI_AUTO=y
+ # CONFIG_IDEDMA_ONLYDISK is not set
+ CONFIG_BLK_DEV_IDEDMA=y
+ # CONFIG_IDEDMA_PCI_WIP is not set
+ CONFIG_BLK_DEV_ADMA100=y
+ CONFIG_BLK_DEV_AEC62XX=y
+ CONFIG_BLK_DEV_ALI15X3=y
+ CONFIG_WDC_ALI15X3=y
+ CONFIG_BLK_DEV_AMD74XX=y
+ CONFIG_AMD74XX_OVERRIDE=y
+ # CONFIG_BLK_DEV_ATIIXP is not set
+ CONFIG_BLK_DEV_CMD64X=y
+ CONFIG_BLK_DEV_TRIFLEX=y
+ CONFIG_BLK_DEV_CY82C693=y
+ CONFIG_BLK_DEV_CS5530=y
+ CONFIG_BLK_DEV_HPT34X=y
+ # CONFIG_HPT34X_AUTODMA is not set
+ CONFIG_BLK_DEV_HPT366=y
+ CONFIG_BLK_DEV_PIIX=y
+ CONFIG_BLK_DEV_NS87415=y
+ # CONFIG_BLK_DEV_OPTI621 is not set
+ CONFIG_BLK_DEV_PDC202XX_OLD=y
+ CONFIG_PDC202XX_BURST=y
+ CONFIG_BLK_DEV_PDC202XX_NEW=y
+ CONFIG_PDC202XX_FORCE=y
+ CONFIG_BLK_DEV_RZ1000=y
+ CONFIG_BLK_DEV_SC1200=y
+ CONFIG_BLK_DEV_SVWKS=y
+ CONFIG_BLK_DEV_SIIMAGE=y
+ CONFIG_BLK_DEV_SIS5513=y
+ CONFIG_BLK_DEV_SLC90E66=y
+ CONFIG_BLK_DEV_TRM290=y
+ CONFIG_BLK_DEV_VIA82CXXX=y
+ CONFIG_IDE_CHIPSETS=y
+ # CONFIG_BLK_DEV_4DRIVES is not set
+ # CONFIG_BLK_DEV_ALI14XX is not set
+ # CONFIG_BLK_DEV_DTC2278 is not set
+ # CONFIG_BLK_DEV_HT6560B is not set
+ # CONFIG_BLK_DEV_PDC4030 is not set
+ # CONFIG_BLK_DEV_QD65XX is not set
+ # CONFIG_BLK_DEV_UMC8672 is not set
+ CONFIG_IDEDMA_AUTO=y
+ # CONFIG_IDEDMA_IVB is not set
+ # CONFIG_DMA_NONPCI is not set
+ CONFIG_BLK_DEV_PDC202XX=y
+ # CONFIG_BLK_DEV_ATARAID is not set
+ # CONFIG_BLK_DEV_ATARAID_PDC is not set
+ # CONFIG_BLK_DEV_ATARAID_HPT is not set
+ # CONFIG_BLK_DEV_ATARAID_MEDLEY is not set
+ # CONFIG_BLK_DEV_ATARAID_SII is not set
+
+ #
+ # SCSI support
+ #
+ CONFIG_SCSI=y
+ CONFIG_BLK_DEV_SD=y
+ CONFIG_SD_EXTRA_DEVS=40
+ # CONFIG_CHR_DEV_ST is not set
+ # CONFIG_CHR_DEV_OSST is not set
+ # CONFIG_BLK_DEV_SR is not set
+ CONFIG_CHR_DEV_SG=y
+ # CONFIG_SCSI_DEBUG_QUEUES is not set
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+
+ #
+ # SCSI low-level drivers
+ #
+ # CONFIG_BLK_DEV_3W_XXXX_RAID is not set
+ # CONFIG_SCSI_7000FASST is not set
+ # CONFIG_SCSI_ACARD is not set
+ # CONFIG_SCSI_AHA152X is not set
+ # CONFIG_SCSI_AHA1542 is not set
+ # CONFIG_SCSI_AHA1740 is not set
+ CONFIG_SCSI_AACRAID=y
+ CONFIG_SCSI_AIC7XXX=y
+ CONFIG_AIC7XXX_CMDS_PER_DEVICE=32
+ CONFIG_AIC7XXX_RESET_DELAY_MS=15000
+ # CONFIG_AIC7XXX_PROBE_EISA_VL is not set
+ # CONFIG_AIC7XXX_BUILD_FIRMWARE is not set
+ # CONFIG_AIC7XXX_DEBUG_ENABLE is not set
+ CONFIG_AIC7XXX_DEBUG_MASK=0
+ # CONFIG_AIC7XXX_REG_PRETTY_PRINT is not set
+ CONFIG_SCSI_AIC79XX=y
+ CONFIG_AIC79XX_CMDS_PER_DEVICE=32
+ CONFIG_AIC79XX_RESET_DELAY_MS=15000
+ # CONFIG_AIC79XX_BUILD_FIRMWARE is not set
+ # CONFIG_AIC79XX_ENABLE_RD_STRM is not set
+ # CONFIG_AIC79XX_DEBUG_ENABLE is not set
+ CONFIG_AIC79XX_DEBUG_MASK=0
+ # CONFIG_AIC79XX_REG_PRETTY_PRINT is not set
+ # CONFIG_SCSI_DPT_I2O is not set
+ # CONFIG_SCSI_ADVANSYS is not set
+ # CONFIG_SCSI_IN2000 is not set
+ # CONFIG_SCSI_AM53C974 is not set
+ CONFIG_SCSI_MEGARAID=y
+ # CONFIG_SCSI_MEGARAID2 is not set
+ CONFIG_SCSI_SATA=y
+ # CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ CONFIG_SCSI_ATA_PIIX=y
+ # CONFIG_SCSI_SATA_NV is not set
+ # CONFIG_SCSI_SATA_QSTOR is not set
+ CONFIG_SCSI_SATA_PROMISE=y
+ CONFIG_SCSI_SATA_SX4=y
+ CONFIG_SCSI_SATA_SIL=y
+ CONFIG_SCSI_SATA_SIS=y
+ # CONFIG_SCSI_SATA_ULI is not set
+ CONFIG_SCSI_SATA_VIA=y
+ CONFIG_SCSI_SATA_VITESSE=y
+ CONFIG_SCSI_BUSLOGIC=y
+ # CONFIG_SCSI_OMIT_FLASHPOINT is not set
+ # CONFIG_SCSI_CPQFCTS is not set
+ # CONFIG_SCSI_DMX3191D is not set
+ # CONFIG_SCSI_DTC3280 is not set
+ # CONFIG_SCSI_EATA is not set
+ # CONFIG_SCSI_EATA_DMA is not set
+ # CONFIG_SCSI_EATA_PIO is not set
+ # CONFIG_SCSI_FUTURE_DOMAIN is not set
+ # CONFIG_SCSI_GDTH is not set
+ # CONFIG_SCSI_GENERIC_NCR5380 is not set
+ # CONFIG_SCSI_IPS is not set
+ # CONFIG_SCSI_INITIO is not set
+ # CONFIG_SCSI_INIA100 is not set
+ # CONFIG_SCSI_NCR53C406A is not set
+ # CONFIG_SCSI_NCR53C7xx is not set
+ CONFIG_SCSI_SYM53C8XX_2=y
+ CONFIG_SCSI_SYM53C8XX_DMA_ADDRESSING_MODE=1
+ CONFIG_SCSI_SYM53C8XX_DEFAULT_TAGS=16
+ CONFIG_SCSI_SYM53C8XX_MAX_TAGS=64
+ # CONFIG_SCSI_SYM53C8XX_IOMAPPED is not set
+ # CONFIG_SCSI_PAS16 is not set
+ # CONFIG_SCSI_PCI2000 is not set
+ # CONFIG_SCSI_PCI2220I is not set
+ # CONFIG_SCSI_PSI240I is not set
+ # CONFIG_SCSI_QLOGIC_FAS is not set
+ # CONFIG_SCSI_QLOGIC_ISP is not set
+ # CONFIG_SCSI_QLOGIC_FC is not set
+ # CONFIG_SCSI_QLOGIC_1280 is not set
+ # CONFIG_SCSI_SEAGATE is not set
+ # CONFIG_SCSI_SIM710 is not set
+ # CONFIG_SCSI_SYM53C416 is not set
+ # CONFIG_SCSI_DC390T is not set
+ # CONFIG_SCSI_T128 is not set
+ # CONFIG_SCSI_U14_34F is not set
+ # CONFIG_SCSI_ULTRASTOR is not set
+ # CONFIG_SCSI_NSP32 is not set
+ # CONFIG_SCSI_DEBUG is not set
+
+ #
+ # Fusion MPT device support
+ #
+ # CONFIG_FUSION is not set
+ # CONFIG_FUSION_BOOT is not set
+ # CONFIG_FUSION_ISENSE is not set
+ # CONFIG_FUSION_CTL is not set
+ # CONFIG_FUSION_LAN is not set
+
+ #
+ # IEEE 1394 (FireWire) support (EXPERIMENTAL)
+ #
+ # CONFIG_IEEE1394 is not set
+
+ #
+ # I2O device support
+ #
+ # CONFIG_I2O is not set
+ # CONFIG_I2O_PCI is not set
+ # CONFIG_I2O_BLOCK is not set
+ # CONFIG_I2O_LAN is not set
+ # CONFIG_I2O_SCSI is not set
+ # CONFIG_I2O_PROC is not set
+
+ #
+ # Network device support
+ #
+ CONFIG_NETDEVICES=y
+
+ #
+ # ARCnet devices
+ #
+ # CONFIG_ARCNET is not set
+ # CONFIG_DUMMY is not set
+ # CONFIG_BONDING is not set
+ # CONFIG_EQUALIZER is not set
+ # CONFIG_TUN is not set
+ # CONFIG_ETHERTAP is not set
+
+ #
+ # Ethernet (10 or 100Mbit)
+ #
+ CONFIG_NET_ETHERNET=y
+ # CONFIG_SUNLANCE is not set
+ # CONFIG_HAPPYMEAL is not set
+ # CONFIG_SUNBMAC is not set
+ # CONFIG_SUNQE is not set
+ # CONFIG_SUNGEM is not set
+ CONFIG_NET_VENDOR_3COM=y
+ # CONFIG_EL1 is not set
+ # CONFIG_EL2 is not set
+ # CONFIG_ELPLUS is not set
+ # CONFIG_EL16 is not set
+ # CONFIG_EL3 is not set
+ # CONFIG_3C515 is not set
+ # CONFIG_ELMC is not set
+ # CONFIG_ELMC_II is not set
+ CONFIG_VORTEX=y
+ # CONFIG_TYPHOON is not set
+ # CONFIG_LANCE is not set
+ # CONFIG_NET_VENDOR_SMC is not set
+ # CONFIG_NET_VENDOR_RACAL is not set
+ # CONFIG_AT1700 is not set
+ # CONFIG_DEPCA is not set
+ # CONFIG_HP100 is not set
+ # CONFIG_NET_ISA is not set
+ CONFIG_NET_PCI=y
+ CONFIG_PCNET32=y
+ # CONFIG_AMD8111_ETH is not set
+ # CONFIG_ADAPTEC_STARFIRE is not set
+ # CONFIG_AC3200 is not set
+ # CONFIG_APRICOT is not set
+ # CONFIG_B44 is not set
+ # CONFIG_CS89x0 is not set
+ # CONFIG_TULIP is not set
+ # CONFIG_DE4X5 is not set
+ # CONFIG_DGRS is not set
+ # CONFIG_DM9102 is not set
+ # CONFIG_EEPRO100 is not set
+ # CONFIG_EEPRO100_PIO is not set
+ CONFIG_E100=y
+ # CONFIG_LNE390 is not set
+ # CONFIG_FEALNX is not set
+ # CONFIG_NATSEMI is not set
+ CONFIG_NE2K_PCI=y
+ # CONFIG_FORCEDETH is not set
+ # CONFIG_NE3210 is not set
+ # CONFIG_ES3210 is not set
+ # CONFIG_8139CP is not set
+ # CONFIG_8139TOO is not set
+ # CONFIG_8139TOO_PIO is not set
+ # CONFIG_8139TOO_TUNE_TWISTER is not set
+ # CONFIG_8139TOO_8129 is not set
+ # CONFIG_8139_OLD_RX_RESET is not set
+ # CONFIG_SIS900 is not set
+ # CONFIG_EPIC100 is not set
+ # CONFIG_SUNDANCE is not set
+ # CONFIG_SUNDANCE_MMIO is not set
+ # CONFIG_TLAN is not set
+ # CONFIG_VIA_RHINE is not set
+ # CONFIG_VIA_RHINE_MMIO is not set
+ # CONFIG_WINBOND_840 is not set
+ # CONFIG_NET_POCKET is not set
+
+ #
+ # Ethernet (1000 Mbit)
+ #
+ # CONFIG_ACENIC is not set
+ # CONFIG_DL2K is not set
+ CONFIG_E1000=y
+ # CONFIG_E1000_NAPI is not set
+ # CONFIG_MYRI_SBUS is not set
+ # CONFIG_NS83820 is not set
+ # CONFIG_HAMACHI is not set
+ # CONFIG_YELLOWFIN is not set
+ # CONFIG_R8169 is not set
+ # CONFIG_SK98LIN is not set
+ CONFIG_TIGON3=y
+ # CONFIG_FDDI is not set
+ # CONFIG_HIPPI is not set
+ # CONFIG_PLIP is not set
+ # CONFIG_PPP is not set
+ # CONFIG_SLIP is not set
+
+ #
+ # Wireless LAN (non-hamradio)
+ #
+ # CONFIG_NET_RADIO is not set
+
+ #
+ # Token Ring devices
+ #
+ # CONFIG_TR is not set
+ # CONFIG_NET_FC is not set
+ # CONFIG_RCPCI is not set
+ # CONFIG_SHAPER is not set
+
+ #
+ # Wan interfaces
+ #
+ # CONFIG_WAN is not set
+
+ #
+ # Amateur Radio support
+ #
+ # CONFIG_HAMRADIO is not set
+
+ #
+ # IrDA (infrared) support
+ #
+ # CONFIG_IRDA is not set
+
+ #
+ # ISDN subsystem
+ #
+ # CONFIG_ISDN is not set
+
+ #
+ # Old CD-ROM drivers (not SCSI, not IDE)
+ #
+ # CONFIG_CD_NO_IDESCSI is not set
+
+ #
+ # Input core support
+ #
+ # CONFIG_INPUT is not set
+ # CONFIG_INPUT_KEYBDEV is not set
+ # CONFIG_INPUT_MOUSEDEV is not set
+ # CONFIG_INPUT_JOYDEV is not set
+ # CONFIG_INPUT_EVDEV is not set
+ # CONFIG_INPUT_UINPUT is not set
+
+ #
+ # Character devices
+ #
+ CONFIG_VT=y
+ CONFIG_VT_CONSOLE=y
+ # CONFIG_SERIAL is not set
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+
+ #
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+
+ #
+ # Mice
+ #
+ # CONFIG_BUSMOUSE is not set
+ CONFIG_MOUSE=y
+ CONFIG_PSMOUSE=y
+ # CONFIG_82C710_MOUSE is not set
+ # CONFIG_PC110_PAD is not set
+ # CONFIG_MK712_MOUSE is not set
+
+ #
+ # Joysticks
+ #
+ # CONFIG_INPUT_GAMEPORT is not set
+ # CONFIG_QIC02_TAPE is not set
+ # CONFIG_IPMI_HANDLER is not set
+ # CONFIG_IPMI_PANIC_EVENT is not set
+ # CONFIG_IPMI_DEVICE_INTERFACE is not set
+ # CONFIG_IPMI_KCS is not set
+ # CONFIG_IPMI_WATCHDOG is not set
+
+ #
+ # Watchdog Cards
+ #
+ # CONFIG_WATCHDOG is not set
+ # CONFIG_SCx200 is not set
+ # CONFIG_SCx200_GPIO is not set
+ # CONFIG_AMD_RNG is not set
+ # CONFIG_INTEL_RNG is not set
+ # CONFIG_HW_RANDOM is not set
+ # CONFIG_AMD_PM768 is not set
+ # CONFIG_NVRAM is not set
+ # CONFIG_RTC is not set
+ # CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_APPLICOM is not set
+ # CONFIG_SONYPI is not set
+
+ #
+ # Ftape, the floppy tape device driver
+ #
+ # CONFIG_FTAPE is not set
+ # CONFIG_AGP is not set
+
+ #
+ # Direct Rendering Manager (XFree86 DRI support)
+ #
+ # CONFIG_DRM is not set
+ # CONFIG_MWAVE is not set
+ # CONFIG_OBMOUSE is not set
+
+ #
+ # Multimedia devices
+ #
+ # CONFIG_VIDEO_DEV is not set
+
+ #
+ # File systems
+ #
+ # CONFIG_QUOTA is not set
+ # CONFIG_QFMT_V2 is not set
+ CONFIG_AUTOFS_FS=y
+ CONFIG_AUTOFS4_FS=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_REISERFS_CHECK is not set
+ # CONFIG_REISERFS_PROC_INFO is not set
+ # CONFIG_ADFS_FS is not set
+ # CONFIG_ADFS_FS_RW is not set
+ # CONFIG_AFFS_FS is not set
+ # CONFIG_HFS_FS is not set
+ # CONFIG_HFSPLUS_FS is not set
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BEFS_DEBUG is not set
+ # CONFIG_BFS_FS is not set
+ CONFIG_EXT3_FS=y
+ CONFIG_JBD=y
+ # CONFIG_JBD_DEBUG is not set
+ CONFIG_FAT_FS=y
+ CONFIG_MSDOS_FS=y
+ CONFIG_UMSDOS_FS=y
+ CONFIG_VFAT_FS=y
+ # CONFIG_EFS_FS is not set
+ # CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ # CONFIG_CRAMFS is not set
+ CONFIG_TMPFS=y
+ CONFIG_RAMFS=y
+ CONFIG_ISO9660_FS=y
+ CONFIG_JOLIET=y
+ CONFIG_ZISOFS=y
+ # CONFIG_JFS_FS is not set
+ # CONFIG_JFS_DEBUG is not set
+ # CONFIG_JFS_STATISTICS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_NTFS_FS is not set
+ # CONFIG_NTFS_RW is not set
+ # CONFIG_HPFS_FS is not set
+ CONFIG_PROC_FS=y
+ # CONFIG_DEVFS_FS is not set
+ # CONFIG_DEVFS_MOUNT is not set
+ # CONFIG_DEVFS_DEBUG is not set
+ CONFIG_DEVPTS_FS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_QNX4FS_RW is not set
+ # CONFIG_ROMFS_FS is not set
+ CONFIG_EXT2_FS=y
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UDF_FS is not set
+ # CONFIG_UDF_RW is not set
+ # CONFIG_UFS_FS is not set
+ # CONFIG_UFS_FS_WRITE is not set
+ # CONFIG_XFS_FS is not set
+ # CONFIG_XFS_QUOTA is not set
+ # CONFIG_XFS_RT is not set
+ # CONFIG_XFS_TRACE is not set
+ # CONFIG_XFS_DEBUG is not set
+
+ #
+ # Network File Systems
+ #
+ # CONFIG_CODA_FS is not set
+ # CONFIG_INTERMEZZO_FS is not set
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_DIRECTIO is not set
+ CONFIG_ROOT_NFS=y
+ CONFIG_NFSD=y
+ CONFIG_NFSD_V3=y
+ # CONFIG_NFSD_TCP is not set
+ CONFIG_SUNRPC=y
+ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
+ # CONFIG_SMB_FS is not set
+ # CONFIG_NCP_FS is not set
+ # CONFIG_NCPFS_PACKET_SIGNING is not set
+ # CONFIG_NCPFS_IOCTL_LOCKING is not set
+ # CONFIG_NCPFS_STRONG is not set
+ # CONFIG_NCPFS_NFS_NS is not set
+ # CONFIG_NCPFS_OS2_NS is not set
+ # CONFIG_NCPFS_SMALLDOS is not set
+ # CONFIG_NCPFS_NLS is not set
+ # CONFIG_NCPFS_EXTRAS is not set
+ CONFIG_ZISOFS_FS=y
+
+ #
+ # Partition Types
+ #
+ CONFIG_PARTITION_ADVANCED=y
+ # CONFIG_ACORN_PARTITION is not set
+ # CONFIG_OSF_PARTITION is not set
+ # CONFIG_AMIGA_PARTITION is not set
+ # CONFIG_ATARI_PARTITION is not set
+ # CONFIG_MAC_PARTITION is not set
+ CONFIG_MSDOS_PARTITION=y
+ # CONFIG_BSD_DISKLABEL is not set
+ # CONFIG_MINIX_SUBPARTITION is not set
+ # CONFIG_SOLARIS_X86_PARTITION is not set
+ # CONFIG_UNIXWARE_DISKLABEL is not set
+ # CONFIG_LDM_PARTITION is not set
+ # CONFIG_SGI_PARTITION is not set
+ # CONFIG_ULTRIX_PARTITION is not set
+ # CONFIG_SUN_PARTITION is not set
+ # CONFIG_EFI_PARTITION is not set
+ # CONFIG_SMB_NLS is not set
+ CONFIG_NLS=y
+
+ #
+ # Native Language Support
+ #
+ CONFIG_NLS_DEFAULT="iso8559-1"
+ # CONFIG_NLS_CODEPAGE_437 is not set
+ # CONFIG_NLS_CODEPAGE_737 is not set
+ # CONFIG_NLS_CODEPAGE_775 is not set
+ # CONFIG_NLS_CODEPAGE_850 is not set
+ # CONFIG_NLS_CODEPAGE_852 is not set
+ # CONFIG_NLS_CODEPAGE_855 is not set
+ # CONFIG_NLS_CODEPAGE_857 is not set
+ # CONFIG_NLS_CODEPAGE_860 is not set
+ # CONFIG_NLS_CODEPAGE_861 is not set
+ # CONFIG_NLS_CODEPAGE_862 is not set
+ # CONFIG_NLS_CODEPAGE_863 is not set
+ # CONFIG_NLS_CODEPAGE_864 is not set
+ # CONFIG_NLS_CODEPAGE_865 is not set
+ # CONFIG_NLS_CODEPAGE_866 is not set
+ # CONFIG_NLS_CODEPAGE_869 is not set
+ # CONFIG_NLS_CODEPAGE_936 is not set
+ # CONFIG_NLS_CODEPAGE_950 is not set
+ # CONFIG_NLS_CODEPAGE_932 is not set
+ # CONFIG_NLS_CODEPAGE_949 is not set
+ # CONFIG_NLS_CODEPAGE_874 is not set
+ # CONFIG_NLS_ISO8859_8 is not set
+ # CONFIG_NLS_CODEPAGE_1250 is not set
+ # CONFIG_NLS_CODEPAGE_1251 is not set
+ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_ISO8859_2 is not set
+ # CONFIG_NLS_ISO8859_3 is not set
+ # CONFIG_NLS_ISO8859_4 is not set
+ # CONFIG_NLS_ISO8859_5 is not set
+ # CONFIG_NLS_ISO8859_6 is not set
+ # CONFIG_NLS_ISO8859_7 is not set
+ # CONFIG_NLS_ISO8859_9 is not set
+ # CONFIG_NLS_ISO8859_13 is not set
+ # CONFIG_NLS_ISO8859_14 is not set
+ # CONFIG_NLS_ISO8859_15 is not set
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+
+ #
+ # Console drivers
+ #
+ CONFIG_XEN_CONSOLE=y
+ CONFIG_VGA_CONSOLE=y
+ CONFIG_DUMMY_CONSOLE=y
+ # CONFIG_VIDEO_SELECT is not set
+ # CONFIG_MDA_CONSOLE is not set
+
+ #
+ # Frame-buffer support
+ #
+ # CONFIG_FB is not set
+
+ #
+ # Sound
+ #
+ # CONFIG_SOUND is not set
+
+ #
+ # USB support
+ #
+ # CONFIG_USB is not set
+
+ #
+ # Support for USB gadgets
+ #
+ # CONFIG_USB_GADGET is not set
+
+ #
+ # Bluetooth support
+ #
+ # CONFIG_BLUEZ is not set
+
+ #
+ # Kernel hacking
+ #
+ CONFIG_DEBUG_KERNEL=y
+ # CONFIG_DEBUG_STACKOVERFLOW is not set
+ # CONFIG_DEBUG_HIGHMEM is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_IOVIRT is not set
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_BUGVERBOSE is not set
+ CONFIG_KALLSYMS=y
+ # CONFIG_FRAME_POINTER is not set
+ CONFIG_LOG_BUF_SHIFT=0
+
+ #
+ # Cryptographic options
+ #
+ CONFIG_CRYPTO=y
+ CONFIG_CRYPTO_HMAC=y
+ CONFIG_CRYPTO_NULL=m
+ CONFIG_CRYPTO_MD4=m
+ CONFIG_CRYPTO_MD5=m
+ CONFIG_CRYPTO_SHA1=m
+ CONFIG_CRYPTO_SHA256=m
+ CONFIG_CRYPTO_SHA512=m
+ # CONFIG_CRYPTO_WP512 is not set
+ CONFIG_CRYPTO_DES=m
+ CONFIG_CRYPTO_BLOWFISH=m
+ CONFIG_CRYPTO_TWOFISH=m
+ CONFIG_CRYPTO_SERPENT=m
+ CONFIG_CRYPTO_AES=m
+ CONFIG_CRYPTO_CAST5=m
+ CONFIG_CRYPTO_CAST6=m
+ # CONFIG_CRYPTO_TEA is not set
+ # CONFIG_CRYPTO_KHAZAD is not set
+ # CONFIG_CRYPTO_ANUBIS is not set
+ CONFIG_CRYPTO_ARC4=m
+ CONFIG_CRYPTO_DEFLATE=m
+ # CONFIG_CRYPTO_MICHAEL_MIC is not set
+ # CONFIG_CRYPTO_TEST is not set
+
+ #
+ # Library routines
+ #
+ # CONFIG_CRC32 is not set
+ CONFIG_ZLIB_INFLATE=y
+ CONFIG_ZLIB_DEFLATE=m
+ # CONFIG_FW_LOADER is not set
--- /dev/null
+ #
+ # Automatically generated make config: don't edit
+ #
+ CONFIG_XEN=y
+ CONFIG_X86=y
+ CONFIG_ISA=y
+ # CONFIG_SBUS is not set
+ CONFIG_UID16=y
+
+ #
+ # Xen
+ #
+ # CONFIG_XEN_PRIVILEGED_GUEST is not set
+ # CONFIG_XEN_PHYSDEV_ACCESS is not set
+ CONFIG_XEN_SCRUB_PAGES=y
+ CONFIG_XEN_NETDEV_FRONTEND=y
+ CONFIG_XEN_BLKDEV_FRONTEND=y
++CONFIG_XEN_BLKDEV_GRANT=y
++# CONFIG_XEN_USB_FRONTEND is not set
+ CONFIG_NO_IDLE_HZ=y
+ # CONFIG_FOREIGN_PAGES is not set
+ CONFIG_NETDEVICES=y
+ # CONFIG_VT is not set
+
+ #
+ # Code maturity level options
+ #
+ CONFIG_EXPERIMENTAL=y
+
+ #
+ # Loadable module support
+ #
+ CONFIG_MODULES=y
+ CONFIG_MODVERSIONS=y
+ CONFIG_KMOD=y
+
+ #
+ # Processor type and features
+ #
+ CONFIG_M686=y
+ # CONFIG_MPENTIUMIII is not set
+ # CONFIG_MPENTIUM4 is not set
+ # CONFIG_MK7 is not set
+ # CONFIG_MK8 is not set
+ # CONFIG_MVIAC3_2 is not set
+ CONFIG_X86_WP_WORKS_OK=y
+ CONFIG_X86_INVLPG=y
+ CONFIG_X86_CMPXCHG=y
+ CONFIG_X86_XADD=y
+ CONFIG_X86_BSWAP=y
+ CONFIG_X86_POPAD_OK=y
+ # CONFIG_RWSEM_GENERIC_SPINLOCK is not set
+ CONFIG_RWSEM_XCHGADD_ALGORITHM=y
+ CONFIG_X86_GOOD_APIC=y
+ CONFIG_X86_PGE=y
+ CONFIG_X86_USE_PPRO_CHECKSUM=y
+ CONFIG_X86_TSC=y
+ CONFIG_X86_L1_CACHE_SHIFT=5
+ CONFIG_NOHIGHMEM=y
+ # CONFIG_HIGHMEM4G is not set
+ CONFIG_FORCE_MAX_ZONEORDER=11
+
+ #
+ # General setup
+ #
+ CONFIG_NET=y
+ CONFIG_SYSVIPC=y
+ # CONFIG_BSD_PROCESS_ACCT is not set
+ CONFIG_SYSCTL=y
+ CONFIG_KCORE_ELF=y
+ # CONFIG_KCORE_AOUT is not set
+ CONFIG_BINFMT_AOUT=y
+ CONFIG_BINFMT_ELF=y
+ # CONFIG_BINFMT_MISC is not set
+ # CONFIG_OOM_KILLER is not set
+
+ #
+ # Networking options
+ #
+ CONFIG_PACKET=y
+ CONFIG_PACKET_MMAP=y
+ # CONFIG_NETLINK_DEV is not set
+ CONFIG_NETFILTER=y
+ # CONFIG_NETFILTER_DEBUG is not set
+ CONFIG_FILTER=y
+ CONFIG_UNIX=y
+ CONFIG_INET=y
+ # CONFIG_IP_MULTICAST is not set
+ # CONFIG_IP_ADVANCED_ROUTER is not set
+ CONFIG_IP_PNP=y
+ CONFIG_IP_PNP_DHCP=y
+ # CONFIG_IP_PNP_BOOTP is not set
+ # CONFIG_IP_PNP_RARP is not set
+ # CONFIG_NET_IPIP is not set
+ # CONFIG_NET_IPGRE is not set
+ # CONFIG_ARPD is not set
+ # CONFIG_INET_ECN is not set
+ # CONFIG_SYN_COOKIES is not set
+
+ #
+ # IP: Netfilter Configuration
+ #
+ CONFIG_IP_NF_CONNTRACK=y
+ CONFIG_IP_NF_FTP=y
+ # CONFIG_IP_NF_AMANDA is not set
+ CONFIG_IP_NF_TFTP=y
+ CONFIG_IP_NF_IRC=y
+ # CONFIG_IP_NF_QUEUE is not set
+ CONFIG_IP_NF_IPTABLES=y
+ # CONFIG_IP_NF_MATCH_LIMIT is not set
+ # CONFIG_IP_NF_MATCH_MAC is not set
+ # CONFIG_IP_NF_MATCH_PKTTYPE is not set
+ # CONFIG_IP_NF_MATCH_MARK is not set
+ # CONFIG_IP_NF_MATCH_MULTIPORT is not set
+ # CONFIG_IP_NF_MATCH_TOS is not set
+ # CONFIG_IP_NF_MATCH_RECENT is not set
+ # CONFIG_IP_NF_MATCH_ECN is not set
+ # CONFIG_IP_NF_MATCH_DSCP is not set
+ # CONFIG_IP_NF_MATCH_AH_ESP is not set
+ # CONFIG_IP_NF_MATCH_LENGTH is not set
+ # CONFIG_IP_NF_MATCH_TTL is not set
+ # CONFIG_IP_NF_MATCH_TCPMSS is not set
+ # CONFIG_IP_NF_MATCH_HELPER is not set
+ CONFIG_IP_NF_MATCH_STATE=y
+ CONFIG_IP_NF_MATCH_CONNTRACK=y
+ # CONFIG_IP_NF_MATCH_UNCLEAN is not set
+ # CONFIG_IP_NF_MATCH_OWNER is not set
+ CONFIG_IP_NF_FILTER=y
+ CONFIG_IP_NF_TARGET_REJECT=y
+ # CONFIG_IP_NF_TARGET_MIRROR is not set
+ CONFIG_IP_NF_NAT=y
+ CONFIG_IP_NF_NAT_NEEDED=y
+ CONFIG_IP_NF_TARGET_MASQUERADE=y
+ CONFIG_IP_NF_TARGET_REDIRECT=y
+ # CONFIG_IP_NF_NAT_SNMP_BASIC is not set
+ CONFIG_IP_NF_NAT_IRC=y
+ CONFIG_IP_NF_NAT_FTP=y
+ CONFIG_IP_NF_NAT_TFTP=y
+ # CONFIG_IP_NF_MANGLE is not set
+ CONFIG_IP_NF_TARGET_LOG=y
+ CONFIG_IP_NF_TARGET_ULOG=y
+ # CONFIG_IP_NF_TARGET_TCPMSS is not set
+ # CONFIG_IP_NF_ARPTABLES is not set
+
+ #
+ # IP: Virtual Server Configuration
+ #
+ # CONFIG_IP_VS is not set
+ # CONFIG_IPV6 is not set
+ # CONFIG_KHTTPD is not set
+
+ #
+ # SCTP Configuration (EXPERIMENTAL)
+ #
+ # CONFIG_IP_SCTP is not set
+ # CONFIG_ATM is not set
+ CONFIG_VLAN_8021Q=y
+
+ #
+ #
+ #
+ # CONFIG_IPX is not set
+ # CONFIG_ATALK is not set
+ # CONFIG_DECNET is not set
+ # CONFIG_BRIDGE is not set
+ # CONFIG_X25 is not set
+ # CONFIG_LAPB is not set
+ # CONFIG_LLC is not set
+ # CONFIG_NET_DIVERT is not set
+ # CONFIG_ECONET is not set
+ # CONFIG_WAN_ROUTER is not set
+ # CONFIG_NET_FASTROUTE is not set
+ # CONFIG_NET_HW_FLOWCONTROL is not set
+
+ #
+ # QoS and/or fair queueing
+ #
+ # CONFIG_NET_SCHED is not set
+
+ #
+ # Network testing
+ #
+ # CONFIG_NET_PKTGEN is not set
+
+ #
+ # SCSI support
+ #
+ CONFIG_SCSI=y
+
+ #
+ # SCSI support type (disk, tape, CD-ROM)
+ #
+ CONFIG_BLK_DEV_SD=y
+ CONFIG_SD_EXTRA_DEVS=40
+ # CONFIG_CHR_DEV_ST is not set
+ # CONFIG_CHR_DEV_OSST is not set
+ # CONFIG_BLK_DEV_SR is not set
+ CONFIG_CHR_DEV_SG=y
+
+ #
+ # Some SCSI devices (e.g. CD jukebox) support multiple LUNs
+ #
+ # CONFIG_SCSI_DEBUG_QUEUES is not set
+ # CONFIG_SCSI_MULTI_LUN is not set
+ # CONFIG_SCSI_CONSTANTS is not set
+ # CONFIG_SCSI_LOGGING is not set
+
+ #
+ # SCSI low-level drivers
+ #
+ # CONFIG_SCSI_7000FASST is not set
+ # CONFIG_SCSI_ACARD is not set
+ # CONFIG_SCSI_AHA152X is not set
+ # CONFIG_SCSI_AHA1542 is not set
+ # CONFIG_SCSI_AHA1740 is not set
+ # CONFIG_SCSI_AACRAID is not set
+ # CONFIG_SCSI_AIC7XXX is not set
+ # CONFIG_SCSI_AIC79XX is not set
+ # CONFIG_SCSI_AIC7XXX_OLD is not set
+ # CONFIG_SCSI_DPT_I2O is not set
+ # CONFIG_SCSI_ADVANSYS is not set
+ # CONFIG_SCSI_IN2000 is not set
+ # CONFIG_SCSI_AM53C974 is not set
+ # CONFIG_SCSI_MEGARAID is not set
+ # CONFIG_SCSI_MEGARAID2 is not set
+ # CONFIG_SCSI_SATA is not set
+ # CONFIG_SCSI_SATA_AHCI is not set
+ # CONFIG_SCSI_SATA_SVW is not set
+ # CONFIG_SCSI_ATA_PIIX is not set
+ # CONFIG_SCSI_SATA_NV is not set
+ # CONFIG_SCSI_SATA_QSTOR is not set
+ # CONFIG_SCSI_SATA_PROMISE is not set
+ # CONFIG_SCSI_SATA_SX4 is not set
+ # CONFIG_SCSI_SATA_SIL is not set
+ # CONFIG_SCSI_SATA_SIS is not set
+ # CONFIG_SCSI_SATA_ULI is not set
+ # CONFIG_SCSI_SATA_VIA is not set
+ # CONFIG_SCSI_SATA_VITESSE is not set
+ # CONFIG_SCSI_BUSLOGIC is not set
+ # CONFIG_SCSI_DMX3191D is not set
+ # CONFIG_SCSI_DTC3280 is not set
+ # CONFIG_SCSI_EATA is not set
+ # CONFIG_SCSI_EATA_DMA is not set
+ # CONFIG_SCSI_EATA_PIO is not set
+ # CONFIG_SCSI_FUTURE_DOMAIN is not set
+ # CONFIG_SCSI_GDTH is not set
+ # CONFIG_SCSI_GENERIC_NCR5380 is not set
+ # CONFIG_SCSI_IPS is not set
+ # CONFIG_SCSI_INITIO is not set
+ # CONFIG_SCSI_INIA100 is not set
+ # CONFIG_SCSI_PPA is not set
+ # CONFIG_SCSI_IMM is not set
+ # CONFIG_SCSI_NCR53C406A is not set
+ # CONFIG_SCSI_NCR53C7xx is not set
+ # CONFIG_SCSI_PAS16 is not set
+ # CONFIG_SCSI_PCI2000 is not set
+ # CONFIG_SCSI_PCI2220I is not set
+ # CONFIG_SCSI_PSI240I is not set
+ # CONFIG_SCSI_QLOGIC_FAS is not set
+ # CONFIG_SCSI_SEAGATE is not set
+ # CONFIG_SCSI_SIM710 is not set
+ # CONFIG_SCSI_SYM53C416 is not set
+ # CONFIG_SCSI_T128 is not set
+ # CONFIG_SCSI_U14_34F is not set
+ # CONFIG_SCSI_ULTRASTOR is not set
+ # CONFIG_SCSI_NSP32 is not set
+ # CONFIG_SCSI_DEBUG is not set
+
+ #
+ # Block devices
+ #
+ CONFIG_BLK_DEV_LOOP=y
+ CONFIG_BLK_DEV_NBD=y
+ CONFIG_BLK_DEV_RAM=y
+ CONFIG_BLK_DEV_RAM_SIZE=4096
+ CONFIG_BLK_DEV_INITRD=y
+ # CONFIG_BLK_STATS is not set
+ # CONFIG_BLK_DEV_HD is not set
+
+ #
+ # Character devices
+ #
+ # CONFIG_VT is not set
+ # CONFIG_SERIAL is not set
+ # CONFIG_SERIAL_EXTENDED is not set
+ # CONFIG_SERIAL_NONSTANDARD is not set
+ CONFIG_UNIX98_PTYS=y
+ CONFIG_UNIX98_PTY_COUNT=256
+ # CONFIG_PRINTER is not set
+ # CONFIG_PPDEV is not set
+ # CONFIG_TIPAR is not set
+
+ #
+ # I2C support
+ #
+ # CONFIG_I2C is not set
+
+ #
+ # Mice
+ #
+ # CONFIG_BUSMOUSE is not set
+ CONFIG_MOUSE=y
+ CONFIG_PSMOUSE=y
+ # CONFIG_82C710_MOUSE is not set
+ # CONFIG_PC110_PAD is not set
+ # CONFIG_MK712_MOUSE is not set
+
+ #
+ # Joysticks
+ #
+ # CONFIG_INPUT_GAMEPORT is not set
+ # CONFIG_INPUT_NS558 is not set
+ # CONFIG_INPUT_LIGHTNING is not set
+ # CONFIG_INPUT_PCIGAME is not set
+ # CONFIG_INPUT_CS461X is not set
+ # CONFIG_INPUT_EMU10K1 is not set
+ # CONFIG_INPUT_SERIO is not set
+ # CONFIG_INPUT_SERPORT is not set
+
+ #
+ # Joysticks
+ #
+ # CONFIG_INPUT_ANALOG is not set
+ # CONFIG_INPUT_A3D is not set
+ # CONFIG_INPUT_ADI is not set
+ # CONFIG_INPUT_COBRA is not set
+ # CONFIG_INPUT_GF2K is not set
+ # CONFIG_INPUT_GRIP is not set
+ # CONFIG_INPUT_INTERACT is not set
+ # CONFIG_INPUT_TMDC is not set
+ # CONFIG_INPUT_SIDEWINDER is not set
+ # CONFIG_INPUT_IFORCE_USB is not set
+ # CONFIG_INPUT_IFORCE_232 is not set
+ # CONFIG_INPUT_WARRIOR is not set
+ # CONFIG_INPUT_MAGELLAN is not set
+ # CONFIG_INPUT_SPACEORB is not set
+ # CONFIG_INPUT_SPACEBALL is not set
+ # CONFIG_INPUT_STINGER is not set
+ # CONFIG_INPUT_DB9 is not set
+ # CONFIG_INPUT_GAMECON is not set
+ # CONFIG_INPUT_TURBOGRAFX is not set
+ # CONFIG_QIC02_TAPE is not set
+ # CONFIG_IPMI_HANDLER is not set
+ # CONFIG_IPMI_PANIC_EVENT is not set
+ # CONFIG_IPMI_DEVICE_INTERFACE is not set
+ # CONFIG_IPMI_KCS is not set
+ # CONFIG_IPMI_WATCHDOG is not set
+
+ #
+ # Watchdog Cards
+ #
+ # CONFIG_WATCHDOG is not set
+ # CONFIG_SCx200 is not set
+ # CONFIG_SCx200_GPIO is not set
+ # CONFIG_AMD_RNG is not set
+ # CONFIG_INTEL_RNG is not set
+ # CONFIG_HW_RANDOM is not set
+ # CONFIG_AMD_PM768 is not set
+ # CONFIG_NVRAM is not set
+ # CONFIG_RTC is not set
+ # CONFIG_DTLK is not set
+ # CONFIG_R3964 is not set
+ # CONFIG_APPLICOM is not set
+ # CONFIG_SONYPI is not set
+
+ #
+ # Ftape, the floppy tape device driver
+ #
+ # CONFIG_FTAPE is not set
+ # CONFIG_AGP is not set
+
+ #
+ # Direct Rendering Manager (XFree86 DRI support)
+ #
+ # CONFIG_DRM is not set
+ # CONFIG_MWAVE is not set
+ # CONFIG_OBMOUSE is not set
+
+ #
+ # File systems
+ #
+ # CONFIG_QUOTA is not set
+ # CONFIG_QFMT_V2 is not set
+ CONFIG_AUTOFS_FS=y
+ CONFIG_AUTOFS4_FS=y
+ # CONFIG_REISERFS_FS is not set
+ # CONFIG_REISERFS_CHECK is not set
+ # CONFIG_REISERFS_PROC_INFO is not set
+ # CONFIG_ADFS_FS is not set
+ # CONFIG_ADFS_FS_RW is not set
+ # CONFIG_AFFS_FS is not set
+ # CONFIG_HFS_FS is not set
+ # CONFIG_HFSPLUS_FS is not set
+ # CONFIG_BEFS_FS is not set
+ # CONFIG_BEFS_DEBUG is not set
+ # CONFIG_BFS_FS is not set
+ CONFIG_EXT3_FS=y
+ CONFIG_JBD=y
+ # CONFIG_JBD_DEBUG is not set
+ CONFIG_FAT_FS=y
+ CONFIG_MSDOS_FS=y
+ CONFIG_UMSDOS_FS=y
+ CONFIG_VFAT_FS=y
+ # CONFIG_EFS_FS is not set
+ # CONFIG_JFFS_FS is not set
+ # CONFIG_JFFS2_FS is not set
+ # CONFIG_CRAMFS is not set
+ CONFIG_TMPFS=y
+ CONFIG_RAMFS=y
+ CONFIG_ISO9660_FS=y
+ CONFIG_JOLIET=y
+ CONFIG_ZISOFS=y
+ # CONFIG_JFS_FS is not set
+ # CONFIG_JFS_DEBUG is not set
+ # CONFIG_JFS_STATISTICS is not set
+ # CONFIG_MINIX_FS is not set
+ # CONFIG_VXFS_FS is not set
+ # CONFIG_NTFS_FS is not set
+ # CONFIG_NTFS_RW is not set
+ # CONFIG_HPFS_FS is not set
+ CONFIG_PROC_FS=y
+ # CONFIG_DEVFS_FS is not set
+ # CONFIG_DEVFS_MOUNT is not set
+ # CONFIG_DEVFS_DEBUG is not set
+ CONFIG_DEVPTS_FS=y
+ # CONFIG_QNX4FS_FS is not set
+ # CONFIG_QNX4FS_RW is not set
+ # CONFIG_ROMFS_FS is not set
+ CONFIG_EXT2_FS=y
+ # CONFIG_SYSV_FS is not set
+ # CONFIG_UDF_FS is not set
+ # CONFIG_UDF_RW is not set
+ # CONFIG_UFS_FS is not set
+ # CONFIG_UFS_FS_WRITE is not set
+ # CONFIG_XFS_FS is not set
+ # CONFIG_XFS_QUOTA is not set
+ # CONFIG_XFS_RT is not set
+ # CONFIG_XFS_TRACE is not set
+ # CONFIG_XFS_DEBUG is not set
+
+ #
+ # Network File Systems
+ #
+ # CONFIG_CODA_FS is not set
+ # CONFIG_INTERMEZZO_FS is not set
+ CONFIG_NFS_FS=y
+ CONFIG_NFS_V3=y
+ # CONFIG_NFS_DIRECTIO is not set
+ CONFIG_ROOT_NFS=y
+ CONFIG_NFSD=y
+ CONFIG_NFSD_V3=y
+ # CONFIG_NFSD_TCP is not set
+ CONFIG_SUNRPC=y
+ CONFIG_LOCKD=y
+ CONFIG_LOCKD_V4=y
+ # CONFIG_SMB_FS is not set
+ # CONFIG_NCP_FS is not set
+ # CONFIG_NCPFS_PACKET_SIGNING is not set
+ # CONFIG_NCPFS_IOCTL_LOCKING is not set
+ # CONFIG_NCPFS_STRONG is not set
+ # CONFIG_NCPFS_NFS_NS is not set
+ # CONFIG_NCPFS_OS2_NS is not set
+ # CONFIG_NCPFS_SMALLDOS is not set
+ # CONFIG_NCPFS_NLS is not set
+ # CONFIG_NCPFS_EXTRAS is not set
+ CONFIG_ZISOFS_FS=y
+
+ #
+ # Partition Types
+ #
+ CONFIG_PARTITION_ADVANCED=y
+ # CONFIG_ACORN_PARTITION is not set
+ # CONFIG_OSF_PARTITION is not set
+ # CONFIG_AMIGA_PARTITION is not set
+ # CONFIG_ATARI_PARTITION is not set
+ # CONFIG_MAC_PARTITION is not set
+ CONFIG_MSDOS_PARTITION=y
+ # CONFIG_BSD_DISKLABEL is not set
+ # CONFIG_MINIX_SUBPARTITION is not set
+ # CONFIG_SOLARIS_X86_PARTITION is not set
+ # CONFIG_UNIXWARE_DISKLABEL is not set
+ # CONFIG_LDM_PARTITION is not set
+ # CONFIG_SGI_PARTITION is not set
+ # CONFIG_ULTRIX_PARTITION is not set
+ # CONFIG_SUN_PARTITION is not set
+ # CONFIG_EFI_PARTITION is not set
+ # CONFIG_SMB_NLS is not set
+ CONFIG_NLS=y
+
+ #
+ # Native Language Support
+ #
+ CONFIG_NLS_DEFAULT="iso8559-1"
+ # CONFIG_NLS_CODEPAGE_437 is not set
+ # CONFIG_NLS_CODEPAGE_737 is not set
+ # CONFIG_NLS_CODEPAGE_775 is not set
+ # CONFIG_NLS_CODEPAGE_850 is not set
+ # CONFIG_NLS_CODEPAGE_852 is not set
+ # CONFIG_NLS_CODEPAGE_855 is not set
+ # CONFIG_NLS_CODEPAGE_857 is not set
+ # CONFIG_NLS_CODEPAGE_860 is not set
+ # CONFIG_NLS_CODEPAGE_861 is not set
+ # CONFIG_NLS_CODEPAGE_862 is not set
+ # CONFIG_NLS_CODEPAGE_863 is not set
+ # CONFIG_NLS_CODEPAGE_864 is not set
+ # CONFIG_NLS_CODEPAGE_865 is not set
+ # CONFIG_NLS_CODEPAGE_866 is not set
+ # CONFIG_NLS_CODEPAGE_869 is not set
+ # CONFIG_NLS_CODEPAGE_936 is not set
+ # CONFIG_NLS_CODEPAGE_950 is not set
+ # CONFIG_NLS_CODEPAGE_932 is not set
+ # CONFIG_NLS_CODEPAGE_949 is not set
+ # CONFIG_NLS_CODEPAGE_874 is not set
+ # CONFIG_NLS_ISO8859_8 is not set
+ # CONFIG_NLS_CODEPAGE_1250 is not set
+ # CONFIG_NLS_CODEPAGE_1251 is not set
+ CONFIG_NLS_ISO8859_1=y
+ # CONFIG_NLS_ISO8859_2 is not set
+ # CONFIG_NLS_ISO8859_3 is not set
+ # CONFIG_NLS_ISO8859_4 is not set
+ # CONFIG_NLS_ISO8859_5 is not set
+ # CONFIG_NLS_ISO8859_6 is not set
+ # CONFIG_NLS_ISO8859_7 is not set
+ # CONFIG_NLS_ISO8859_9 is not set
+ # CONFIG_NLS_ISO8859_13 is not set
+ # CONFIG_NLS_ISO8859_14 is not set
+ # CONFIG_NLS_ISO8859_15 is not set
+ # CONFIG_NLS_KOI8_R is not set
+ # CONFIG_NLS_KOI8_U is not set
+ # CONFIG_NLS_UTF8 is not set
+
+ #
+ # Console drivers
+ #
+ CONFIG_XEN_CONSOLE=y
+
+ #
+ # Kernel hacking
+ #
+ CONFIG_DEBUG_KERNEL=y
+ # CONFIG_DEBUG_STACKOVERFLOW is not set
+ # CONFIG_DEBUG_HIGHMEM is not set
+ # CONFIG_DEBUG_SLAB is not set
+ # CONFIG_DEBUG_IOVIRT is not set
+ # CONFIG_MAGIC_SYSRQ is not set
+ # CONFIG_DEBUG_SPINLOCK is not set
+ # CONFIG_DEBUG_BUGVERBOSE is not set
+ CONFIG_KALLSYMS=y
+ # CONFIG_FRAME_POINTER is not set
+ CONFIG_LOG_BUF_SHIFT=0
+
+ #
+ # Cryptographic options
+ #
+ # CONFIG_CRYPTO is not set
+
+ #
+ # Library routines
+ #
+ # CONFIG_CRC32 is not set
+ CONFIG_ZLIB_INFLATE=y
+ # CONFIG_ZLIB_DEFLATE is not set
--- /dev/null
- /*
- * Update of partition info, and check of usage count, is protected
- * by the per-block-device semaphore.
- */
- down(&bd->bd_sem);
-
+ /******************************************************************************
+ * arch/xen/drivers/blkif/frontend/vbd.c
+ *
+ * Xenolinux virtual block-device driver.
+ *
+ * Copyright (c) 2003-2004, Keir Fraser & Steve Hand
+ * Modifications by Mark A. Williamson are (c) Intel Research Cambridge
+ */
+
+ #include "common.h"
+ #include <linux/blk.h>
+
+ /*
+ * For convenience we distinguish between ide, scsi and 'other' (i.e.
+ * potentially combinations of the two) in the naming scheme and in a few
+ * other places (like default readahead, etc).
+ */
+ #define XLIDE_MAJOR_NAME "hd"
+ #define XLSCSI_MAJOR_NAME "sd"
+ #define XLVBD_MAJOR_NAME "xvd"
+
+ #define XLIDE_DEVS_PER_MAJOR 2
+ #define XLSCSI_DEVS_PER_MAJOR 16
+ #define XLVBD_DEVS_PER_MAJOR 16
+
+ #define XLIDE_PARTN_SHIFT 6 /* amount to shift minor to get 'real' minor */
+ #define XLIDE_MAX_PART (1 << XLIDE_PARTN_SHIFT) /* minors per ide vbd */
+
+ #define XLSCSI_PARTN_SHIFT 4 /* amount to shift minor to get 'real' minor */
+ #define XLSCSI_MAX_PART (1 << XLSCSI_PARTN_SHIFT) /* minors per scsi vbd */
+
+ #define XLVBD_PARTN_SHIFT 4 /* amount to shift minor to get 'real' minor */
+ #define XLVBD_MAX_PART (1 << XLVBD_PARTN_SHIFT) /* minors per 'other' vbd */
+
+ /* The below are for the generic drivers/block/ll_rw_block.c code. */
+ static int xlide_blksize_size[256];
+ static int xlide_hardsect_size[256];
+ static int xlide_max_sectors[256];
+ static int xlscsi_blksize_size[256];
+ static int xlscsi_hardsect_size[256];
+ static int xlscsi_max_sectors[256];
+ static int xlvbd_blksize_size[256];
+ static int xlvbd_hardsect_size[256];
+ static int xlvbd_max_sectors[256];
+
+ /* Information about our VBDs. */
+ #define MAX_VBDS 64
+ static int nr_vbds;
+ static vdisk_t *vbd_info;
+
+ static struct block_device_operations xlvbd_block_fops =
+ {
+ open: blkif_open,
+ release: blkif_release,
+ ioctl: blkif_ioctl,
+ check_media_change: blkif_check,
+ revalidate: blkif_revalidate,
+ };
+
+ static int xlvbd_get_vbd_info(vdisk_t *disk_info)
+ {
+ vdisk_t *buf = (vdisk_t *)__get_free_page(GFP_KERNEL);
+ blkif_request_t req;
+ blkif_response_t rsp;
+ int nr;
+
+ memset(&req, 0, sizeof(req));
+ req.operation = BLKIF_OP_PROBE;
+ req.nr_segments = 1;
++#ifdef CONFIG_XEN_BLKDEV_GRANT
++ blkif_control_probe_send(&req, &rsp,
++ (unsigned long)(virt_to_machine(buf)));
++#else
+ req.frame_and_sects[0] = virt_to_machine(buf) | 7;
+
+ blkif_control_send(&req, &rsp);
++#endif
+
+ if ( rsp.status <= 0 )
+ {
+ printk(KERN_ALERT "Could not probe disks (%d)\n", rsp.status);
+ return -1;
+ }
+
+ if ( (nr = rsp.status) > MAX_VBDS )
+ nr = MAX_VBDS;
+ memcpy(disk_info, buf, nr * sizeof(vdisk_t));
+
+ return nr;
+ }
+
+ /*
+ * xlvbd_init_device - initialise a VBD device
+ * @disk: a vdisk_t describing the VBD
+ *
+ * Takes a vdisk_t * that describes a VBD the domain has access to.
+ * Performs appropriate initialisation and registration of the device.
+ *
+ * Care needs to be taken when making re-entrant calls to ensure that
+ * corruption does not occur. Also, devices that are in use should not have
+ * their details updated. This is the caller's responsibility.
+ */
+ static int xlvbd_init_device(vdisk_t *xd)
+ {
+ int device = xd->device;
+ int major = MAJOR(device);
+ int minor = MINOR(device);
+ int is_ide = IDE_DISK_MAJOR(major); /* is this an ide device? */
+ int is_scsi= SCSI_BLK_MAJOR(major); /* is this a scsi device? */
+ char *major_name;
+ struct gendisk *gd;
+ struct block_device *bd;
+ xl_disk_t *disk;
+ int i, rc = 0, max_part, partno;
+ unsigned long capacity;
+
+ unsigned char buf[64];
+
+ if ( (bd = bdget(device)) == NULL )
+ return -1;
+
- } else if (VDISK_VIRTUAL(xd->info)) {
-
- major_name = XLVBD_MAJOR_NAME;
- max_part = XLVBD_MAX_PART;
-
+ if ( ((disk = xldev_to_xldisk(device)) != NULL) && (disk->usage != 0) )
+ {
+ printk(KERN_ALERT "VBD update failed - in use [dev=%x]\n", device);
+ rc = -1;
+ goto out;
+ }
+
+ if ( is_ide ) {
+
+ major_name = XLIDE_MAJOR_NAME;
+ max_part = XLIDE_MAX_PART;
+
+ } else if ( is_scsi ) {
+
+ major_name = XLSCSI_MAJOR_NAME;
+ max_part = XLSCSI_MAX_PART;
+
- if ( VDISK_READONLY(xd->info) )
- set_device_ro(device, 1);
+ } else {
+
+ /* SMH: hmm - probably a CCISS driver or sim; assume CCISS for now */
+ printk(KERN_ALERT "Assuming device %02x:%02x is CCISS/SCSI\n",
+ major, minor);
+ is_scsi = 1;
+ major_name = "cciss";
+ max_part = XLSCSI_MAX_PART;
+
+ }
+
+ partno = minor & (max_part - 1);
+
+ if ( (gd = get_gendisk(device)) == NULL )
+ {
+ rc = register_blkdev(major, major_name, &xlvbd_block_fops);
+ if ( rc < 0 )
+ {
+ printk(KERN_ALERT "XL VBD: can't get major %d\n", major);
+ goto out;
+ }
+
+ if ( is_ide )
+ {
+ blksize_size[major] = xlide_blksize_size;
+ hardsect_size[major] = xlide_hardsect_size;
+ max_sectors[major] = xlide_max_sectors;
+ read_ahead[major] = 8;
+ }
+ else if ( is_scsi )
+ {
+ blksize_size[major] = xlscsi_blksize_size;
+ hardsect_size[major] = xlscsi_hardsect_size;
+ max_sectors[major] = xlscsi_max_sectors;
+ read_ahead[major] = 8;
+ }
+ else
+ {
+ blksize_size[major] = xlvbd_blksize_size;
+ hardsect_size[major] = xlvbd_hardsect_size;
+ max_sectors[major] = xlvbd_max_sectors;
+ read_ahead[major] = 8;
+ }
+
+ blk_init_queue(BLK_DEFAULT_QUEUE(major), do_blkif_request);
+
+ /*
+ * Turn off barking 'headactive' mode. We dequeue buffer heads as
+ * soon as we pass them to the back-end driver.
+ */
+ blk_queue_headactive(BLK_DEFAULT_QUEUE(major), 0);
+
+ /* Construct an appropriate gendisk structure. */
+ gd = kmalloc(sizeof(struct gendisk), GFP_KERNEL);
+ gd->major = major;
+ gd->major_name = major_name;
+
+ gd->max_p = max_part;
+ if ( is_ide )
+ {
+ gd->minor_shift = XLIDE_PARTN_SHIFT;
+ gd->nr_real = XLIDE_DEVS_PER_MAJOR;
+ }
+ else if ( is_scsi )
+ {
+ gd->minor_shift = XLSCSI_PARTN_SHIFT;
+ gd->nr_real = XLSCSI_DEVS_PER_MAJOR;
+ }
+ else
+ {
+ gd->minor_shift = XLVBD_PARTN_SHIFT;
+ gd->nr_real = XLVBD_DEVS_PER_MAJOR;
+ }
+
+ /*
+ ** The sizes[] and part[] arrays hold the sizes and other
+ ** information about every partition with this 'major' (i.e.
+ ** every disk sharing the 8 bit prefix * max partns per disk)
+ */
+ gd->sizes = kmalloc(max_part*gd->nr_real*sizeof(int), GFP_KERNEL);
+ gd->part = kmalloc(max_part*gd->nr_real*sizeof(struct hd_struct),
+ GFP_KERNEL);
+ memset(gd->sizes, 0, max_part * gd->nr_real * sizeof(int));
+ memset(gd->part, 0, max_part * gd->nr_real
+ * sizeof(struct hd_struct));
+
+
+ gd->real_devices = kmalloc(gd->nr_real * sizeof(xl_disk_t),
+ GFP_KERNEL);
+ memset(gd->real_devices, 0, gd->nr_real * sizeof(xl_disk_t));
+
+ gd->next = NULL;
+ gd->fops = &xlvbd_block_fops;
+
+ gd->de_arr = kmalloc(gd->nr_real * sizeof(*gd->de_arr),
+ GFP_KERNEL);
+ gd->flags = kmalloc(gd->nr_real * sizeof(*gd->flags), GFP_KERNEL);
+
+ memset(gd->de_arr, 0, gd->nr_real * sizeof(*gd->de_arr));
+ memset(gd->flags, 0, gd->nr_real * sizeof(*gd->flags));
+
+ add_gendisk(gd);
+
+ blk_size[major] = gd->sizes;
+ }
+
- switch ( VDISK_TYPE(xd->info) )
++ if ( xd->info & VDISK_READONLY )
++ set_device_ro(device, 1);
+
+ gd->flags[minor >> gd->minor_shift] |= GENHD_FL_XEN;
+
+ /* NB. Linux 2.4 only handles 32-bit sector offsets and capacities. */
+ capacity = (unsigned long)xd->capacity;
+
+ if ( partno != 0 )
+ {
+ /*
+ * If this was previously set up as a real disc we will have set
+ * up partition-table information. Virtual partitions override
+ * 'real' partitions, and the two cannot coexist on a device.
+ */
+ if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) &&
+ (gd->sizes[minor & ~(max_part-1)] != 0) )
+ {
+ /*
+ * Any non-zero sub-partition entries must be cleaned out before
+ * installing 'virtual' partition entries. The two types cannot
+ * coexist, and virtual partitions are favoured.
+ */
+ kdev_t dev = device & ~(max_part-1);
+ for ( i = max_part - 1; i > 0; i-- )
+ {
+ invalidate_device(dev+i, 1);
+ gd->part[MINOR(dev+i)].start_sect = 0;
+ gd->part[MINOR(dev+i)].nr_sects = 0;
+ gd->sizes[MINOR(dev+i)] = 0;
+ }
+ printk(KERN_ALERT
+ "Virtual partitions found for /dev/%s - ignoring any "
+ "real partition information we may have found.\n",
+ disk_name(gd, MINOR(device), buf));
+ }
+
+ /* Need to skankily setup 'partition' information */
+ gd->part[minor].start_sect = 0;
+ gd->part[minor].nr_sects = capacity;
+ gd->sizes[minor] = capacity >>(BLOCK_SIZE_BITS-9);
+
+ gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS;
+ }
+ else
+ {
+ gd->part[minor].nr_sects = capacity;
+ gd->sizes[minor] = capacity>>(BLOCK_SIZE_BITS-9);
+
+ /* Some final fix-ups depending on the device type */
- case VDISK_TYPE_CDROM:
- case VDISK_TYPE_FLOPPY:
- case VDISK_TYPE_TAPE:
++ if ( xd->info & VDISK_REMOVABLE )
+ {
- VDISK_TYPE(xd->info)==VDISK_TYPE_CDROM ? "cdrom" :
- (VDISK_TYPE(xd->info)==VDISK_TYPE_TAPE ? "tape" :
- "floppy"), disk_name(gd, MINOR(device), buf));
- break;
-
- case VDISK_TYPE_DISK:
+ gd->flags[minor >> gd->minor_shift] |= GENHD_FL_REMOVABLE;
+ printk(KERN_ALERT
+ "Skipping partition check on %s /dev/%s\n",
- break;
-
- default:
- printk(KERN_ALERT "XenoLinux: unknown device type %d\n",
- VDISK_TYPE(xd->info));
- break;
++ (xd->info & VDISK_CDROM) ? "cdrom" : "removable",
++ disk_name(gd, MINOR(device), buf));
++ }
++ else
++ {
+ /* Only check partitions on real discs (not virtual!). */
+ if ( gd->flags[minor>>gd->minor_shift] & GENHD_FL_VIRT_PARTNS )
+ {
+ printk(KERN_ALERT
+ "Skipping partition check on virtual /dev/%s\n",
+ disk_name(gd, MINOR(device), buf));
+ break;
+ }
+ register_disk(gd, device, gd->max_p, &xlvbd_block_fops, capacity);
- up(&bd->bd_sem);
+ }
+ }
+
+ out:
- /*
- * Update of partition info, and check of usage count, is protected
- * by the per-block-device semaphore.
- */
- down(&bd->bd_sem);
-
+ bdput(bd);
+ return rc;
+ }
+
+
+ /*
+ * xlvbd_remove_device - remove a device node if possible
+ * @device: numeric device ID
+ *
+ * Updates the gendisk structure and invalidates devices.
+ *
+ * This is OK for now but in future, should perhaps consider where this should
+ * deallocate gendisks / unregister devices.
+ */
+ static int xlvbd_remove_device(int device)
+ {
+ int i, rc = 0, minor = MINOR(device);
+ struct gendisk *gd;
+ struct block_device *bd;
+ xl_disk_t *disk = NULL;
+
+ if ( (bd = bdget(device)) == NULL )
+ return -1;
+
- up(&bd->bd_sem);
+ if ( ((gd = get_gendisk(device)) == NULL) ||
+ ((disk = xldev_to_xldisk(device)) == NULL) )
+ BUG();
+
+ if ( disk->usage != 0 )
+ {
+ printk(KERN_ALERT "VBD removal failed - in use [dev=%x]\n", device);
+ rc = -1;
+ goto out;
+ }
+
+ if ( (minor & (gd->max_p-1)) != 0 )
+ {
+ /* 1: The VBD is mapped to a partition rather than a whole unit. */
+ invalidate_device(device, 1);
+ gd->part[minor].start_sect = 0;
+ gd->part[minor].nr_sects = 0;
+ gd->sizes[minor] = 0;
+
+ /* Clear the consists-of-virtual-partitions flag if possible. */
+ gd->flags[minor >> gd->minor_shift] &= ~GENHD_FL_VIRT_PARTNS;
+ for ( i = 1; i < gd->max_p; i++ )
+ if ( gd->sizes[(minor & ~(gd->max_p-1)) + i] != 0 )
+ gd->flags[minor >> gd->minor_shift] |= GENHD_FL_VIRT_PARTNS;
+
+ /*
+ * If all virtual partitions are now gone, and a 'whole unit' VBD is
+ * present, then we can try to grok the unit's real partition table.
+ */
+ if ( !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS) &&
+ (gd->sizes[minor & ~(gd->max_p-1)] != 0) &&
+ !(gd->flags[minor >> gd->minor_shift] & GENHD_FL_REMOVABLE) )
+ {
+ register_disk(gd,
+ device&~(gd->max_p-1),
+ gd->max_p,
+ &xlvbd_block_fops,
+ gd->part[minor&~(gd->max_p-1)].nr_sects);
+ }
+ }
+ else
+ {
+ /*
+ * 2: The VBD is mapped to an entire 'unit'. Clear all partitions.
+ * NB. The partition entries are only cleared if there are no VBDs
+ * mapped to individual partitions on this unit.
+ */
+ i = gd->max_p - 1; /* Default: clear subpartitions as well. */
+ if ( gd->flags[minor >> gd->minor_shift] & GENHD_FL_VIRT_PARTNS )
+ i = 0; /* 'Virtual' mode: only clear the 'whole unit' entry. */
+ while ( i >= 0 )
+ {
+ invalidate_device(device+i, 1);
+ gd->part[minor+i].start_sect = 0;
+ gd->part[minor+i].nr_sects = 0;
+ gd->sizes[minor+i] = 0;
+ i--;
+ }
+ }
+
+ out:
+ bdput(bd);
+ return rc;
+ }
+
+ /*
+ * xlvbd_update_vbds - reprobes the VBD status and performs updates driver
+ * state. The VBDs need to be updated in this way when the domain is
+ * initialised and also each time we receive an XLBLK_UPDATE event.
+ */
+ void xlvbd_update_vbds(void)
+ {
+ int i, j, k, old_nr, new_nr;
+ vdisk_t *old_info, *new_info, *merged_info;
+
+ old_info = vbd_info;
+ old_nr = nr_vbds;
+
+ new_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
+ if (!new_info)
+ return;
+
+ if ( unlikely(new_nr = xlvbd_get_vbd_info(new_info)) < 0 )
+ goto out;
+
+ /*
+ * Final list maximum size is old list + new list. This occurs only when
+ * old list and new list do not overlap at all, and we cannot yet destroy
+ * VBDs in the old list because the usage counts are busy.
+ */
+ merged_info = kmalloc((old_nr + new_nr) * sizeof(vdisk_t), GFP_KERNEL);
+ if (!merged_info)
+ goto out;
+
+ /* @i tracks old list; @j tracks new list; @k tracks merged list. */
+ i = j = k = 0;
+
+ while ( (i < old_nr) && (j < new_nr) )
+ {
+ if ( old_info[i].device < new_info[j].device )
+ {
+ if ( xlvbd_remove_device(old_info[i].device) != 0 )
+ memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
+ i++;
+ }
+ else if ( old_info[i].device > new_info[j].device )
+ {
+ if ( xlvbd_init_device(&new_info[j]) == 0 )
+ memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
+ j++;
+ }
+ else
+ {
+ if ( ((old_info[i].capacity == new_info[j].capacity) &&
+ (old_info[i].info == new_info[j].info)) ||
+ (xlvbd_remove_device(old_info[i].device) != 0) )
+ memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
+ else if ( xlvbd_init_device(&new_info[j]) == 0 )
+ memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
+ i++; j++;
+ }
+ }
+
+ for ( ; i < old_nr; i++ )
+ {
+ if ( xlvbd_remove_device(old_info[i].device) != 0 )
+ memcpy(&merged_info[k++], &old_info[i], sizeof(vdisk_t));
+ }
+
+ for ( ; j < new_nr; j++ )
+ {
+ if ( xlvbd_init_device(&new_info[j]) == 0 )
+ memcpy(&merged_info[k++], &new_info[j], sizeof(vdisk_t));
+ }
+
+ vbd_info = merged_info;
+ nr_vbds = k;
+
+ kfree(old_info);
+ out:
+ kfree(new_info);
+ }
+
+
+ /*
+ * Set up all the linux device goop for the virtual block devices (vbd's) that
+ * we know about. Note that although from the backend driver's p.o.v. VBDs are
+ * addressed simply an opaque 16-bit device number, the domain creation tools
+ * conventionally allocate these numbers to correspond to those used by 'real'
+ * linux -- this is just for convenience as it means e.g. that the same
+ * /etc/fstab can be used when booting with or without Xen.
+ */
+ int xlvbd_init(void)
+ {
+ int i;
+
+ /*
+ * If compiled as a module, we don't support unloading yet. We therefore
+ * permanently increment the reference count to disallow it.
+ */
+ SET_MODULE_OWNER(&xlvbd_block_fops);
+ MOD_INC_USE_COUNT;
+
+ /* Initialize the global arrays. */
+ for ( i = 0; i < 256; i++ )
+ {
+ xlide_blksize_size[i] = 1024;
+ xlide_hardsect_size[i] = 512;
+ xlide_max_sectors[i] = 512;
+
+ xlscsi_blksize_size[i] = 1024;
+ xlscsi_hardsect_size[i] = 512;
+ xlscsi_max_sectors[i] = 512;
+
+ xlvbd_blksize_size[i] = 512;
+ xlvbd_hardsect_size[i] = 512;
+ xlvbd_max_sectors[i] = 512;
+ }
+
+ vbd_info = kmalloc(MAX_VBDS * sizeof(vdisk_t), GFP_KERNEL);
+ if (!vbd_info)
+ return -ENOMEM;
+
+ nr_vbds = xlvbd_get_vbd_info(vbd_info);
+
+ if ( nr_vbds < 0 )
+ {
+ kfree(vbd_info);
+ vbd_info = NULL;
+ nr_vbds = 0;
+ }
+ else
+ {
+ for ( i = 0; i < nr_vbds; i++ )
+ xlvbd_init_device(&vbd_info[i]);
+ }
+
+ return 0;
+ }
--- /dev/null
-export-objs := i386_ksyms.o skbuff.o ctrl_if.o
+
+ .S.o:
+ $(CC) $(AFLAGS) -traditional -c $< -o $*.o
+
+ all: kernel.o head.o init_task.o
+
+ O_TARGET := kernel.o
+
- reboot.o fixup.o skbuff.o
++export-objs := i386_ksyms.o gnttab.o skbuff.o ctrl_if.o
+
+ obj-y := process.o semaphore.o signal.o entry.o traps.o irq.o \
+ ptrace.o ioport.o ldt.o setup.o time.o sys_i386.o \
+ i386_ksyms.o i387.o evtchn.o ctrl_if.o pci-dma.o \
++ reboot.o fixup.o gnttab.o skbuff.o
+
+ ifdef CONFIG_PCI
+ obj-y += pci-i386.o pci-pc.o
+ endif
+
+ include $(TOPDIR)/Rules.make
--- /dev/null
- .asciz "GUEST_OS=linux,GUEST_VER=2.4,XEN_VER=2.0,VIRT_BASE=0xC0000000"
+
+ .section __xen_guest
++ .ascii "GUEST_OS=linux,GUEST_VER=2.4,XEN_VER=3.0,VIRT_BASE=0xC0000000"
++ .ascii ",LOADER=generic"
++ .byte 0
+
+ .text
+ #include <linux/config.h>
+ #include <linux/threads.h>
+ #include <linux/linkage.h>
+ #include <asm/segment.h>
+ #include <asm/page.h>
+ #include <asm/pgtable.h>
+ #include <asm/desc.h>
+
+ ENTRY(stext)
+ ENTRY(_stext)
+ cld
+ lss stack_start,%esp
+ /* Copy the necessary stuff from xen_start_info structure. */
+ mov $SYMBOL_NAME(xen_start_info_union),%edi
+ mov $128,%ecx
+ rep movsl
+ jmp SYMBOL_NAME(start_kernel)
+
+ ENTRY(stack_start)
+ .long SYMBOL_NAME(init_task_union)+8192, __KERNEL_DS
+
+ .org 0x1000
+ ENTRY(empty_zero_page)
+
+ .org 0x2000
+ ENTRY(default_ldt)
+
+ .org 0x3000
+ ENTRY(cpu0_pte_quicklist)
+
+ .org 0x3400
+ ENTRY(cpu0_pgd_quicklist)
+
+ .org 0x3800
--- /dev/null
- flush_page_update_queue();
+ /*
+ * linux/kernel/ldt.c
+ *
+ * Copyright (C) 1992 Krishna Balasubramanian and Linus Torvalds
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/string.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/vmalloc.h>
+ #include <linux/slab.h>
+
++#include <asm/mmu_context.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/ldt.h>
+ #include <asm/desc.h>
+
+ #ifdef CONFIG_SMP /* avoids "defined but not used" warnig */
+ static void flush_ldt(void *mm)
+ {
+ if (current->active_mm)
+ load_LDT(¤t->active_mm->context);
+ }
+ #endif
+
+ static int alloc_ldt(mm_context_t *pc, int mincount, int reload)
+ {
+ void *oldldt;
+ void *newldt;
+ int oldsize;
+
+ if (mincount <= pc->size)
+ return 0;
+ oldsize = pc->size;
+ mincount = (mincount+511)&(~511);
+ if (mincount*LDT_ENTRY_SIZE > PAGE_SIZE)
+ newldt = vmalloc(mincount*LDT_ENTRY_SIZE);
+ else
+ newldt = kmalloc(mincount*LDT_ENTRY_SIZE, GFP_KERNEL);
+
+ if (!newldt)
+ return -ENOMEM;
+
+ if (oldsize)
+ memcpy(newldt, pc->ldt, oldsize*LDT_ENTRY_SIZE);
+
+ oldldt = pc->ldt;
+ memset(newldt+oldsize*LDT_ENTRY_SIZE, 0, (mincount-oldsize)*LDT_ENTRY_SIZE);
+ wmb();
+ pc->ldt = newldt;
+ pc->size = mincount;
+ if (reload) {
+ make_pages_readonly(
+ pc->ldt,
+ (pc->size*LDT_ENTRY_SIZE)/PAGE_SIZE);
+ load_LDT(pc);
- flush_page_update_queue();
+ #ifdef CONFIG_SMP
+ if (current->mm->cpu_vm_mask != (1<<smp_processor_id()))
+ smp_call_function(flush_ldt, 0, 1, 1);
+ #endif
+ }
+ wmb();
+ if (oldsize) {
++ make_pages_writable(
++ oldldt, (oldsize*LDT_ENTRY_SIZE)/PAGE_SIZE);
+ if (oldsize*LDT_ENTRY_SIZE > PAGE_SIZE)
+ vfree(oldldt);
+ else
+ kfree(oldldt);
+ }
+ return 0;
+ }
+
+ static inline int copy_ldt(mm_context_t *new, mm_context_t *old)
+ {
+ int err = alloc_ldt(new, old->size, 0);
+ if (err < 0) {
+ printk(KERN_WARNING "ldt allocation failed\n");
+ new->size = 0;
+ return err;
+ }
+ memcpy(new->ldt, old->ldt, old->size*LDT_ENTRY_SIZE);
+ make_pages_readonly(new->ldt, (new->size*LDT_ENTRY_SIZE)/PAGE_SIZE);
+ return 0;
+ }
+
+ /*
+ * we do not have to muck with descriptors here, that is
+ * done in switch_mm() as needed.
+ */
+ int init_new_context(struct task_struct *tsk, struct mm_struct *mm)
+ {
+ struct mm_struct * old_mm;
+ int retval = 0;
+
+ init_MUTEX(&mm->context.sem);
+ mm->context.size = 0;
+ old_mm = current->mm;
+ if (old_mm && old_mm->context.size > 0) {
+ down(&old_mm->context.sem);
+ retval = copy_ldt(&mm->context, &old_mm->context);
+ up(&old_mm->context.sem);
+ }
+ return retval;
+ }
+
+ /*
+ * No need to lock the MM as we are the last user
+ * Do not touch the ldt register, we are already
+ * in the next thread.
+ */
+ void destroy_context(struct mm_struct *mm)
+ {
+ if (mm->context.size) {
+ make_pages_writable(
+ mm->context.ldt,
+ (mm->context.size*LDT_ENTRY_SIZE)/PAGE_SIZE);
+ if (mm->context.size*LDT_ENTRY_SIZE > PAGE_SIZE)
+ vfree(mm->context.ldt);
+ else
+ kfree(mm->context.ldt);
+ mm->context.size = 0;
+ }
+ }
+
+ static int read_ldt(void * ptr, unsigned long bytecount)
+ {
+ int err;
+ unsigned long size;
+ struct mm_struct * mm = current->mm;
+
+ if (!mm->context.size)
+ return 0;
+ if (bytecount > LDT_ENTRY_SIZE*LDT_ENTRIES)
+ bytecount = LDT_ENTRY_SIZE*LDT_ENTRIES;
+
+ down(&mm->context.sem);
+ size = mm->context.size*LDT_ENTRY_SIZE;
+ if (size > bytecount)
+ size = bytecount;
+
+ err = 0;
+ if (copy_to_user(ptr, mm->context.ldt, size))
+ err = -EFAULT;
+ up(&mm->context.sem);
+ if (err < 0)
+ return err;
+ if (size != bytecount) {
+ /* zero-fill the rest */
+ clear_user(ptr+size, bytecount-size);
+ }
+ return bytecount;
+ }
+
+ static int read_default_ldt(void * ptr, unsigned long bytecount)
+ {
+ int err;
+ unsigned long size;
+ void *address;
+
+ err = 0;
+ address = &default_ldt[0];
+ size = 5*sizeof(struct desc_struct);
+ if (size > bytecount)
+ size = bytecount;
+
+ err = size;
+ if (copy_to_user(ptr, address, size))
+ err = -EFAULT;
+
+ return err;
+ }
+
+ static int write_ldt(void * ptr, unsigned long bytecount, int oldmode)
+ {
+ struct mm_struct * mm = current->mm;
+ __u32 entry_1, entry_2, *lp;
+ unsigned long mach_lp;
+ int error;
+ struct modify_ldt_ldt_s ldt_info;
+
+ error = -EINVAL;
+ if (bytecount != sizeof(ldt_info))
+ goto out;
+ error = -EFAULT;
+ if (copy_from_user(&ldt_info, ptr, sizeof(ldt_info)))
+ goto out;
+
+ error = -EINVAL;
+ if (ldt_info.entry_number >= LDT_ENTRIES)
+ goto out;
+ if (ldt_info.contents == 3) {
+ if (oldmode)
+ goto out;
+ if (ldt_info.seg_not_present == 0)
+ goto out;
+ }
+
+ down(&mm->context.sem);
+ if (ldt_info.entry_number >= mm->context.size) {
+ error = alloc_ldt(¤t->mm->context, ldt_info.entry_number+1, 1);
+ if (error < 0)
+ goto out_unlock;
+ }
+
+ lp = (__u32 *) ((ldt_info.entry_number << 3) + (char *) mm->context.ldt);
+ mach_lp = arbitrary_virt_to_machine(lp);
+
+ /* Allow LDTs to be cleared by the user. */
+ if (ldt_info.base_addr == 0 && ldt_info.limit == 0) {
+ if (oldmode ||
+ (ldt_info.contents == 0 &&
+ ldt_info.read_exec_only == 1 &&
+ ldt_info.seg_32bit == 0 &&
+ ldt_info.limit_in_pages == 0 &&
+ ldt_info.seg_not_present == 1 &&
+ ldt_info.useable == 0 )) {
+ entry_1 = 0;
+ entry_2 = 0;
+ goto install;
+ }
+ }
+
+ entry_1 = ((ldt_info.base_addr & 0x0000ffff) << 16) |
+ (ldt_info.limit & 0x0ffff);
+ entry_2 = (ldt_info.base_addr & 0xff000000) |
+ ((ldt_info.base_addr & 0x00ff0000) >> 16) |
+ (ldt_info.limit & 0xf0000) |
+ ((ldt_info.read_exec_only ^ 1) << 9) |
+ (ldt_info.contents << 10) |
+ ((ldt_info.seg_not_present ^ 1) << 15) |
+ (ldt_info.seg_32bit << 22) |
+ (ldt_info.limit_in_pages << 23) |
+ 0x7000;
+ if (!oldmode)
+ entry_2 |= (ldt_info.useable << 20);
+
+ /* Install the new entry ... */
+ install:
+ error = HYPERVISOR_update_descriptor(mach_lp, entry_1, entry_2);
+
+ out_unlock:
+ up(&mm->context.sem);
+ out:
+ return error;
+ }
+
+ asmlinkage int sys_modify_ldt(int func, void *ptr, unsigned long bytecount)
+ {
+ int ret = -ENOSYS;
+
+ switch (func) {
+ case 0:
+ ret = read_ldt(ptr, bytecount);
+ break;
+ case 1:
+ ret = write_ldt(ptr, bytecount, 1);
+ break;
+ case 2:
+ ret = read_default_ldt(ptr, bytecount);
+ break;
+ case 0x11:
+ ret = write_ldt(ptr, bytecount, 0);
+ break;
+ }
+ return ret;
+ }
--- /dev/null
-#include <asm/multicall.h>
-#include <asm-xen/xen-public/dom0_ops.h>
+ /*
+ * linux/arch/i386/kernel/process.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * Pentium III FXSR, SSE support
+ * Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+ /*
+ * This file handles the architecture-dependent parts of process handling..
+ */
+
+ #define __KERNEL_SYSCALLS__
+ #include <stdarg.h>
+
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/stddef.h>
+ #include <linux/unistd.h>
+ #include <linux/ptrace.h>
+ #include <linux/slab.h>
+ #include <linux/vmalloc.h>
+ #include <linux/user.h>
+ #include <linux/a.out.h>
+ #include <linux/interrupt.h>
+ #include <linux/config.h>
+ #include <linux/delay.h>
+ #include <linux/reboot.h>
+ #include <linux/init.h>
+ #include <linux/mc146818rtc.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #include <asm/ldt.h>
+ #include <asm/processor.h>
+ #include <asm/i387.h>
+ #include <asm/desc.h>
+ #include <asm/mmu_context.h>
- unsigned long eflags;
++#include <asm-xen/xen-public/physdev.h>
+
+ #include <linux/irq.h>
+
+ asmlinkage void ret_from_fork(void) __asm__("ret_from_fork");
+
+ int hlt_counter;
+
+ /*
+ * Powermanagement idle function, if any..
+ */
+ void (*pm_idle)(void);
+
+ /*
+ * Power off function, if any
+ */
+ void (*pm_power_off)(void);
+
+ void disable_hlt(void)
+ {
+ hlt_counter++;
+ }
+
+ void enable_hlt(void)
+ {
+ hlt_counter--;
+ }
+
+ /*
+ * The idle thread. There's no useful work to be
+ * done, so just try to conserve power and have a
+ * low exit latency (ie sit in a loop waiting for
+ * somebody to say that they'd like to reschedule)
+ */
+ void cpu_idle (void)
+ {
+ extern int set_timeout_timer(void);
+
+ /* Endless idle loop with no priority at all. */
+ init_idle();
+ current->nice = 20;
+ current->counter = -100;
+
+ for ( ; ; )
+ {
+ while ( !current->need_resched )
+ {
+ __cli();
+ if ( current->need_resched )
+ {
+ /* The race-free check for events failed. */
+ __sti();
+ break;
+ }
+ else if ( set_timeout_timer() == 0 )
+ {
+ /* NB. Blocking reenable events in a race-free manner. */
+ HYPERVISOR_block();
+ }
+ else
+ {
+ /* No race here: yielding will get us the CPU again anyway. */
+ __sti();
+ HYPERVISOR_yield();
+ }
+ }
+ schedule();
+ check_pgt_cache();
+ }
+ }
+
+ extern void show_trace(unsigned long* esp);
+
+ void show_regs(struct pt_regs * regs)
+ {
+ printk("\n");
+ printk("Pid: %d, comm: %20s\n", current->pid, current->comm);
+ printk("EIP: %04x:[<%08lx>] CPU: %d",0xffff & regs->xcs,regs->eip, smp_processor_id());
+ if (regs->xcs & 2)
+ printk(" ESP: %04x:%08lx",0xffff & regs->xss,regs->esp);
+ printk(" EFLAGS: %08lx %s\n",regs->eflags, print_tainted());
+ printk("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n",
+ regs->eax,regs->ebx,regs->ecx,regs->edx);
+ printk("ESI: %08lx EDI: %08lx EBP: %08lx",
+ regs->esi, regs->edi, regs->ebp);
+ printk(" DS: %04x ES: %04x\n",
+ 0xffff & regs->xds,0xffff & regs->xes);
+
+ show_trace(®s->esp);
+ }
+
+
+ /*
+ * Create a kernel thread
+ */
+ int arch_kernel_thread(int (*fn)(void *), void * arg, unsigned long flags)
+ {
+ long retval, d0;
+
+ __asm__ __volatile__(
+ "movl %%esp,%%esi\n\t"
+ "int $0x80\n\t" /* Linux/i386 system call */
+ "cmpl %%esp,%%esi\n\t" /* child or parent? */
+ "je 1f\n\t" /* parent - jump */
+ /* Load the argument into eax, and push it. That way, it does
+ * not matter whether the called function is compiled with
+ * -mregparm or not. */
+ "movl %4,%%eax\n\t"
+ "pushl %%eax\n\t"
+ "call *%5\n\t" /* call fn */
+ "movl %3,%0\n\t" /* exit */
+ "int $0x80\n"
+ "1:\t"
+ :"=&a" (retval), "=&S" (d0)
+ :"0" (__NR_clone), "i" (__NR_exit),
+ "r" (arg), "r" (fn),
+ "b" (flags | CLONE_VM)
+ : "memory");
+
+ return retval;
+ }
+
+ /*
+ * Free current thread data structures etc..
+ */
+ void exit_thread(void)
+ {
+ /* nothing to do ... */
+ }
+
+ void flush_thread(void)
+ {
+ struct task_struct *tsk = current;
+
+ memset(tsk->thread.debugreg, 0, sizeof(unsigned long)*8);
+
+ /*
+ * Forget coprocessor state..
+ */
+ clear_fpu(tsk);
+ tsk->used_math = 0;
+ }
+
+ void release_thread(struct task_struct *dead_task)
+ {
+ if (dead_task->mm) {
+ // temporary debugging check
+ if (dead_task->mm->context.size) {
+ printk("WARNING: dead process %8s still has LDT? <%p/%08x>\n",
+ dead_task->comm,
+ dead_task->mm->context.ldt,
+ dead_task->mm->context.size);
+ BUG();
+ }
+ }
+ //release_x86_irqs(dead_task);
+ }
+
+
+ /*
+ * Save a segment.
+ */
+ #define savesegment(seg,value) \
+ asm volatile("movl %%" #seg ",%0":"=m" (*(int *)&(value)))
+
+ int copy_thread(int nr, unsigned long clone_flags, unsigned long esp,
+ unsigned long unused,
+ struct task_struct * p, struct pt_regs * regs)
+ {
+ struct pt_regs * childregs;
-
- __asm__ __volatile__ ( "pushfl; popl %0" : "=r" (eflags) : );
- p->thread.io_pl = (eflags >> 12) & 3;
+
+ childregs = ((struct pt_regs *) (THREAD_SIZE + (unsigned long) p)) - 1;
+ struct_cpy(childregs, regs);
+ childregs->eax = 0;
+ childregs->esp = esp;
+
+ p->thread.esp = (unsigned long) childregs;
+ p->thread.esp0 = (unsigned long) (childregs+1);
+
+ p->thread.eip = (unsigned long) ret_from_fork;
+
+ savesegment(fs,p->thread.fs);
+ savesegment(gs,p->thread.gs);
+
+ unlazy_fpu(current);
+ struct_cpy(&p->thread.i387, ¤t->thread.i387);
+
-
- __cli();
-
- /*
- * We clobber FS and GS here so that we avoid a GPF when restoring previous
- * task's FS/GS values in Xen when the LDT is switched. If we don't do this
- * then we can end up erroneously re-flushing the page-update queue when
- * we 'execute_multicall_list'.
- */
- __asm__ __volatile__ (
- "xorl %%eax,%%eax; movl %%eax,%%fs; movl %%eax,%%gs" : : : "eax" );
-
- MULTICALL_flush_page_update_queue();
++ p->thread.io_pl = current->thread.io_pl;
+
+ return 0;
+ }
+
+ /*
+ * fill in the user structure for a core dump..
+ */
+ void dump_thread(struct pt_regs * regs, struct user * dump)
+ {
+ int i;
+
+ /* changed the size calculations - should hopefully work better. lbt */
+ dump->magic = CMAGIC;
+ dump->start_code = 0;
+ dump->start_stack = regs->esp & ~(PAGE_SIZE - 1);
+ dump->u_tsize = ((unsigned long) current->mm->end_code) >> PAGE_SHIFT;
+ dump->u_dsize = ((unsigned long) (current->mm->brk + (PAGE_SIZE-1))) >> PAGE_SHIFT;
+ dump->u_dsize -= dump->u_tsize;
+ dump->u_ssize = 0;
+ for (i = 0; i < 8; i++)
+ dump->u_debugreg[i] = current->thread.debugreg[i];
+
+ if (dump->start_stack < TASK_SIZE)
+ dump->u_ssize = ((unsigned long) (TASK_SIZE - dump->start_stack)) >> PAGE_SHIFT;
+
+ dump->regs.ebx = regs->ebx;
+ dump->regs.ecx = regs->ecx;
+ dump->regs.edx = regs->edx;
+ dump->regs.esi = regs->esi;
+ dump->regs.edi = regs->edi;
+ dump->regs.ebp = regs->ebp;
+ dump->regs.eax = regs->eax;
+ dump->regs.ds = regs->xds;
+ dump->regs.es = regs->xes;
+ savesegment(fs,dump->regs.fs);
+ savesegment(gs,dump->regs.gs);
+ dump->regs.orig_eax = regs->orig_eax;
+ dump->regs.eip = regs->eip;
+ dump->regs.cs = regs->xcs;
+ dump->regs.eflags = regs->eflags;
+ dump->regs.esp = regs->esp;
+ dump->regs.ss = regs->xss;
+
+ dump->u_fpvalid = dump_fpu (regs, &dump->i387);
+ }
+
+ /*
+ * switch_to(x,yn) should switch tasks from x to y.
+ *
+ * We fsave/fwait so that an exception goes off at the right time
+ * (as a call from the fsave or fwait in effect) rather than to
+ * the wrong process. Lazy FP saving no longer makes any sense
+ * with modern CPU's, and this simplifies a lot of things (SMP
+ * and UP become the same).
+ *
+ * NOTE! We used to use the x86 hardware context switching. The
+ * reason for not using it any more becomes apparent when you
+ * try to recover gracefully from saved state that is no longer
+ * valid (stale segment register values in particular). With the
+ * hardware task-switch, there is no way to fix up bad state in
+ * a reasonable manner.
+ *
+ * The fact that Intel documents the hardware task-switching to
+ * be slow is a fairly red herring - this code is not noticeably
+ * faster. However, there _is_ some room for improvement here,
+ * so the performance issues may eventually be a valid point.
+ * More important, however, is the fact that this allows us much
+ * more flexibility.
+ */
+ void fastcall __switch_to(struct task_struct *prev_p, struct task_struct *next_p)
+ {
+ struct thread_struct *next = &next_p->thread;
- queue_multicall0(__HYPERVISOR_fpu_taskswitch);
++ physdev_op_t op;
++ multicall_entry_t _mcl[8], *mcl = _mcl;
+
+ /*
+ * This is basically 'unlazy_fpu', except that we queue a multicall to
+ * indicate FPU task switch, rather than synchronously trapping to Xen.
+ */
+ if ( prev_p->flags & PF_USEDFPU )
+ {
+ if ( cpu_has_fxsr )
+ asm volatile( "fxsave %0 ; fnclex"
+ : "=m" (prev_p->thread.i387.fxsave) );
+ else
+ asm volatile( "fnsave %0 ; fwait"
+ : "=m" (prev_p->thread.i387.fsave) );
+ prev_p->flags &= ~PF_USEDFPU;
- queue_multicall2(__HYPERVISOR_stack_switch, __KERNEL_DS, next->esp0);
- if ( xen_start_info.flags & SIF_PRIVILEGED )
++ mcl->op = __HYPERVISOR_fpu_taskswitch;
++ mcl->args[0] = 1;
++ mcl++;
+ }
+
- dom0_op_t op;
- op.cmd = DOM0_IOPL;
- op.u.iopl.domain = DOMID_SELF;
- op.u.iopl.iopl = next->io_pl;
- op.interface_version = DOM0_INTERFACE_VERSION;
- queue_multicall1(__HYPERVISOR_dom0_op, (unsigned long)&op);
++ mcl->op = __HYPERVISOR_stack_switch;
++ mcl->args[0] = __KERNEL_DS;
++ mcl->args[1] = next->esp0;
++ mcl++;
++
++ if ( prev_p->thread.io_pl != next->io_pl )
+ {
- /* EXECUTE ALL TASK SWITCH XEN SYSCALLS AT THIS POINT. */
- execute_multicall_list();
- __sti();
++ op.cmd = PHYSDEVOP_SET_IOPL;
++ op.u.set_iopl.iopl = next->io_pl;
++ mcl->op = __HYPERVISOR_physdev_op;
++ mcl->args[0] = (unsigned long)&op;
++ mcl++;
+ }
+
++ (void)HYPERVISOR_multicall(_mcl, mcl - _mcl);
+
+ /*
+ * Restore %fs and %gs.
+ */
+ loadsegment(fs, next->fs);
+ loadsegment(gs, next->gs);
+
+ /*
+ * Now maybe reload the debug registers
+ */
+ if ( next->debugreg[7] != 0 )
+ {
+ HYPERVISOR_set_debugreg(0, next->debugreg[0]);
+ HYPERVISOR_set_debugreg(1, next->debugreg[1]);
+ HYPERVISOR_set_debugreg(2, next->debugreg[2]);
+ HYPERVISOR_set_debugreg(3, next->debugreg[3]);
+ /* no 4 and 5 */
+ HYPERVISOR_set_debugreg(6, next->debugreg[6]);
+ HYPERVISOR_set_debugreg(7, next->debugreg[7]);
+ }
+ }
+
+ asmlinkage int sys_fork(struct pt_regs regs)
+ {
+ return do_fork(SIGCHLD, regs.esp, ®s, 0);
+ }
+
+ asmlinkage int sys_clone(struct pt_regs regs)
+ {
+ unsigned long clone_flags;
+ unsigned long newsp;
+
+ clone_flags = regs.ebx;
+ newsp = regs.ecx;
+ if (!newsp)
+ newsp = regs.esp;
+ return do_fork(clone_flags, newsp, ®s, 0);
+ }
+
+ /*
+ * This is trivial, and on the face of it looks like it
+ * could equally well be done in user mode.
+ *
+ * Not so, for quite unobvious reasons - register pressure.
+ * In user mode vfork() cannot have a stack frame, and if
+ * done by calling the "clone()" system call directly, you
+ * do not have enough call-clobbered registers to hold all
+ * the information you need.
+ */
+ asmlinkage int sys_vfork(struct pt_regs regs)
+ {
+ return do_fork(CLONE_VFORK | CLONE_VM | SIGCHLD, regs.esp, ®s, 0);
+ }
+
+ /*
+ * sys_execve() executes a new program.
+ */
+ asmlinkage int sys_execve(struct pt_regs regs)
+ {
+ int error;
+ char * filename;
+
+ filename = getname((char *) regs.ebx);
+ error = PTR_ERR(filename);
+ if (IS_ERR(filename))
+ goto out;
+ error = do_execve(filename, (char **) regs.ecx, (char **) regs.edx, ®s);
+ if (error == 0)
+ current->ptrace &= ~PT_DTRACE;
+ putname(filename);
+ out:
+ return error;
+ }
+
+ /*
+ * These bracket the sleeping functions..
+ */
+ extern void scheduling_functions_start_here(void);
+ extern void scheduling_functions_end_here(void);
+ #define first_sched ((unsigned long) scheduling_functions_start_here)
+ #define last_sched ((unsigned long) scheduling_functions_end_here)
+
+ unsigned long get_wchan(struct task_struct *p)
+ {
+ unsigned long ebp, esp, eip;
+ unsigned long stack_page;
+ int count = 0;
+ if (!p || p == current || p->state == TASK_RUNNING)
+ return 0;
+ stack_page = (unsigned long)p;
+ esp = p->thread.esp;
+ if (!stack_page || esp < stack_page || esp > 8188+stack_page)
+ return 0;
+ /* include/asm-i386/system.h:switch_to() pushes ebp last. */
+ ebp = *(unsigned long *) esp;
+ do {
+ if (ebp < stack_page || ebp > 8184+stack_page)
+ return 0;
+ eip = *(unsigned long *) (ebp+4);
+ if (eip < first_sched || eip >= last_sched)
+ return eip;
+ ebp = *(unsigned long *) ebp;
+ } while (count++ < 16);
+ return 0;
+ }
+ #undef last_sched
+ #undef first_sched
--- /dev/null
-#include <asm-xen/xen-public/dom0_ops.h>
+ /*
+ * linux/arch/i386/kernel/setup.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+ /*
+ * This file handles the architecture-dependent parts of initialization
+ */
+
+ #define __KERNEL_SYSCALLS__
+ static int errno;
+ #include <linux/errno.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/mm.h>
+ #include <linux/stddef.h>
+ #include <linux/unistd.h>
+ #include <linux/ptrace.h>
+ #include <linux/slab.h>
+ #include <linux/user.h>
+ #include <linux/a.out.h>
+ #include <linux/tty.h>
+ #include <linux/ioport.h>
+ #include <linux/delay.h>
+ #include <linux/config.h>
+ #include <linux/init.h>
+ #include <linux/apm_bios.h>
+ #ifdef CONFIG_BLK_DEV_RAM
+ #include <linux/blk.h>
+ #endif
+ #include <linux/highmem.h>
+ #include <linux/bootmem.h>
+ #include <linux/seq_file.h>
+ #include <linux/reboot.h>
+ #include <asm/processor.h>
+ #include <linux/console.h>
+ #include <linux/module.h>
+ #include <asm/mtrr.h>
+ #include <asm/uaccess.h>
+ #include <asm/system.h>
+ #include <asm/io.h>
+ #include <asm/smp.h>
+ #include <asm/msr.h>
+ #include <asm/desc.h>
+ #include <asm/dma.h>
+ #include <asm/mpspec.h>
+ #include <asm/mmu_context.h>
+ #include <asm/ctrl_if.h>
+ #include <asm/hypervisor.h>
-unsigned long *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
-
-multicall_entry_t multicall_list[8];
-int nr_multicall_ents = 0;
++#include <asm-xen/xen-public/physdev.h>
+ #include <linux/netdevice.h>
+ #include <linux/rtnetlink.h>
+ #include <linux/tqueue.h>
+ #include <net/pkt_sched.h> /* dev_(de)activate */
+
+ /*
+ * Point at the empty zero page to start with. We map the real shared_info
+ * page as soon as fixmap is up and running.
+ */
+ shared_info_t *HYPERVISOR_shared_info = (shared_info_t *)empty_zero_page;
+
- HYPERVISOR_vm_assist(VMASST_CMD_enable,
- VMASST_TYPE_4gb_segments);
++unsigned int *phys_to_machine_mapping, *pfn_to_mfn_frame_list;
+
+ /*
+ * Machine setup..
+ */
+
+ char ignore_irq13; /* set if exception 16 works */
+ struct cpuinfo_x86 boot_cpu_data = { 0, 0, 0, 0, -1, 1, 0, 0, -1 };
+
+ unsigned long mmu_cr4_features;
+
+ unsigned char * vgacon_mmap;
+
+ /*
+ * Bus types ..
+ */
+ #ifdef CONFIG_EISA
+ int EISA_bus;
+ #endif
+ int MCA_bus;
+
+ /* for MCA, but anyone else can use it if they want */
+ unsigned int machine_id;
+ unsigned int machine_submodel_id;
+ unsigned int BIOS_revision;
+ unsigned int mca_pentium_flag;
+
+ /* For PCI or other memory-mapped resources */
+ unsigned long pci_mem_start = 0x10000000;
+
+ /*
+ * Setup options
+ */
+ struct drive_info_struct { char dummy[32]; } drive_info;
+ struct screen_info screen_info;
+ struct apm_info apm_info;
+ struct sys_desc_table_struct {
+ unsigned short length;
+ unsigned char table[0];
+ };
+
+ unsigned char aux_device_present;
+
+ extern int root_mountflags;
+ extern char _text, _etext, _edata, _end;
+
+ extern int blk_nohighio;
+
+ int enable_acpi_smp_table;
+
+ /* Raw start-of-day parameters from the hypervisor. */
+ union xen_start_info_union xen_start_info_union;
+
+ #define COMMAND_LINE_SIZE 256
+ static char command_line[COMMAND_LINE_SIZE];
+ char saved_command_line[COMMAND_LINE_SIZE];
+
+ /* parse_mem_cmdline()
+ * returns the value of the mem= boot param converted to pages or 0
+ */
+ static int __init parse_mem_cmdline (char ** cmdline_p)
+ {
+ char c = ' ', *to = command_line, *from = saved_command_line;
+ int len = 0;
+ unsigned long long bytes;
+ int mem_param = 0;
+
+ /* Save unparsed command line copy for /proc/cmdline */
+ memcpy(saved_command_line, xen_start_info.cmd_line, COMMAND_LINE_SIZE);
+ saved_command_line[COMMAND_LINE_SIZE-1] = '\0';
+
+ for (;;) {
+ /*
+ * "mem=nopentium" disables the 4MB page tables.
+ * "mem=XXX[kKmM]" defines a memory region from HIGH_MEM
+ * to <mem>, overriding the bios size.
+ * "mem=XXX[KkmM]@XXX[KkmM]" defines a memory region from
+ * <start> to <start>+<mem>, overriding the bios size.
+ */
+ if (c == ' ' && !memcmp(from, "mem=", 4)) {
+ if (to != command_line)
+ to--;
+ if (!memcmp(from+4, "nopentium", 9)) {
+ from += 9+4;
+ } else if (!memcmp(from+4, "exactmap", 8)) {
+ from += 8+4;
+ } else {
+ bytes = memparse(from+4, &from);
+ mem_param = bytes>>PAGE_SHIFT;
+ if (*from == '@')
+ (void)memparse(from+1, &from);
+ }
+ }
+
+ c = *(from++);
+ if (!c)
+ break;
+ if (COMMAND_LINE_SIZE <= ++len)
+ break;
+ *(to++) = c;
+ }
+ *to = '\0';
+ *cmdline_p = command_line;
+
+ return mem_param;
+ }
+
+ /*
+ * Every exception-fixup table is sorted (i.e., kernel main table, and every
+ * module table. Some elements may be out of order if they reference text.init,
+ * for example.
+ */
+ static void sort_exception_table(struct exception_table_entry *start,
+ struct exception_table_entry *end)
+ {
+ struct exception_table_entry *p, *q, tmp;
+
+ for ( p = start; p < end; p++ )
+ {
+ for ( q = p-1; q > start; q-- )
+ if ( p->insn > q->insn )
+ break;
+ if ( ++q != p )
+ {
+ tmp = *p;
+ memmove(q+1, q, (p-q)*sizeof(*p));
+ *q = tmp;
+ }
+ }
+ }
+
+ int xen_module_init(struct module *mod)
+ {
+ sort_exception_table(mod->ex_table_start, mod->ex_table_end);
+ return 0;
+ }
+
+ void __init setup_arch(char **cmdline_p)
+ {
+ int i,j;
+ unsigned long bootmap_size, start_pfn, lmax_low_pfn;
+ int mem_param; /* user specified memory size in pages */
+ int boot_pfn; /* low pages available for bootmem */
++ physdev_op_t op;
+
+ extern void hypervisor_callback(void);
+ extern void failsafe_callback(void);
+
+ extern unsigned long cpu0_pte_quicklist[];
+ extern unsigned long cpu0_pgd_quicklist[];
+
+ extern const struct exception_table_entry __start___ex_table[];
+ extern const struct exception_table_entry __stop___ex_table[];
+
+ extern char _stext;
+
+ /* Force a quick death if the kernel panics. */
+ extern int panic_timeout;
+ if ( panic_timeout == 0 )
+ panic_timeout = 1;
+
+ /* Ensure that the kernel exception-fixup table is sorted. */
+ sort_exception_table(__start___ex_table, __stop___ex_table);
+
+ #ifndef CONFIG_HIGHIO
+ blk_nohighio = 1;
+ #endif
+
- phys_to_machine_mapping = (unsigned long *)xen_start_info.mfn_list;
++ HYPERVISOR_vm_assist(
++ VMASST_CMD_enable, VMASST_TYPE_4gb_segments);
++ HYPERVISOR_vm_assist(
++ VMASST_CMD_enable, VMASST_TYPE_writable_pagetables);
+
+ HYPERVISOR_set_callbacks(
+ __KERNEL_CS, (unsigned long)hypervisor_callback,
+ __KERNEL_CS, (unsigned long)failsafe_callback);
+
+ boot_cpu_data.pgd_quick = cpu0_pgd_quicklist;
+ boot_cpu_data.pte_quick = cpu0_pte_quicklist;
+
+ /* This must be initialized to UNNAMED_MAJOR for ipconfig to work
+ properly. Setting ROOT_DEV to default to /dev/ram0 breaks initrd. */
+ ROOT_DEV = MKDEV(UNNAMED_MAJOR,0);
+ memset(&drive_info, 0, sizeof(drive_info));
+ memset(&screen_info, 0, sizeof(screen_info));
+
+ /* This is drawn from a dump from vgacon:startup in standard Linux. */
+ screen_info.orig_video_mode = 3;
+ screen_info.orig_video_isVGA = 1;
+ screen_info.orig_video_lines = 25;
+ screen_info.orig_video_cols = 80;
+ screen_info.orig_video_ega_bx = 3;
+ screen_info.orig_video_points = 16;
+
+ memset(&apm_info.bios, 0, sizeof(apm_info.bios));
+ aux_device_present = 0;
+ #ifdef CONFIG_BLK_DEV_RAM
+ rd_image_start = 0;
+ rd_prompt = 0;
+ rd_doload = 0;
+ #endif
+
+ root_mountflags &= ~MS_RDONLY;
+ init_mm.start_code = (unsigned long) &_text;
+ init_mm.end_code = (unsigned long) &_etext;
+ init_mm.end_data = (unsigned long) &_edata;
+ init_mm.brk = (unsigned long) &_end;
+
+ /* The mem= kernel command line param overrides the detected amount
+ * of memory. For xenolinux, if this override is larger than detected
+ * memory, then boot using only detected memory and make provisions to
+ * use all of the override value. The hypervisor can give this
+ * domain more memory later on and it will be added to the free
+ * lists at that time. See claim_new_pages() in
+ * arch/xen/drivers/balloon/balloon.c
+ */
+ mem_param = parse_mem_cmdline(cmdline_p);
+ if (mem_param < xen_start_info.nr_pages)
+ mem_param = xen_start_info.nr_pages;
+
+ #define PFN_UP(x) (((x) + PAGE_SIZE-1) >> PAGE_SHIFT)
+ #define PFN_DOWN(x) ((x) >> PAGE_SHIFT)
+ #define PFN_PHYS(x) ((x) << PAGE_SHIFT)
+
+ /*
+ * 128MB for vmalloc(), iomap(), kmap(), and fixaddr mappings.
+ */
+ #define VMALLOC_RESERVE (unsigned long)(128 << 20)
+ #define MAXMEM (unsigned long)(HYPERVISOR_VIRT_START-PAGE_OFFSET-VMALLOC_RESERVE)
+ #define MAXMEM_PFN PFN_DOWN(MAXMEM)
+ #define MAX_NONPAE_PFN (1 << 20)
+
+ /*
+ * Determine low and high memory ranges:
+ */
+ lmax_low_pfn = max_pfn = mem_param;
+ if (lmax_low_pfn > MAXMEM_PFN) {
+ lmax_low_pfn = MAXMEM_PFN;
+ #ifndef CONFIG_HIGHMEM
+ /* Maximum memory usable is what is directly addressable */
+ printk(KERN_WARNING "Warning only %ldMB will be used.\n",
+ MAXMEM>>20);
+ if (max_pfn > MAX_NONPAE_PFN)
+ printk(KERN_WARNING "Use a PAE enabled kernel.\n");
+ else
+ printk(KERN_WARNING "Use a HIGHMEM enabled kernel.\n");
+ max_pfn = lmax_low_pfn;
+ #else /* !CONFIG_HIGHMEM */
+ #ifndef CONFIG_X86_PAE
+ if (max_pfn > MAX_NONPAE_PFN) {
+ max_pfn = MAX_NONPAE_PFN;
+ printk(KERN_WARNING "Warning only 4GB will be used.\n");
+ printk(KERN_WARNING "Use a PAE enabled kernel.\n");
+ }
+ #endif /* !CONFIG_X86_PAE */
+ #endif /* !CONFIG_HIGHMEM */
+ }
+
+ #ifdef CONFIG_HIGHMEM
+ highstart_pfn = highend_pfn = max_pfn;
+ if (max_pfn > MAXMEM_PFN) {
+ highstart_pfn = MAXMEM_PFN;
+ printk(KERN_NOTICE "%ldMB HIGHMEM available.\n",
+ pages_to_mb(highend_pfn - highstart_pfn));
+ }
+ #endif
+
- /* If we are a privileged guest OS then we should request IO privileges. */
- if ( xen_start_info.flags & SIF_PRIVILEGED )
- {
- dom0_op_t op;
- op.cmd = DOM0_IOPL;
- op.u.iopl.domain = DOMID_SELF;
- op.u.iopl.iopl = 1;
- if( HYPERVISOR_dom0_op(&op) != 0 )
- panic("Unable to obtain IOPL, despite being SIF_PRIVILEGED");
- current->thread.io_pl = 1;
- }
++ phys_to_machine_mapping = (unsigned int *)xen_start_info.mfn_list;
+ cur_pgd = init_mm.pgd = (pgd_t *)xen_start_info.pt_base;
+
+ start_pfn = (__pa(xen_start_info.pt_base) >> PAGE_SHIFT) +
+ xen_start_info.nr_pt_frames;
+
+ /*
+ * Initialize the boot-time allocator, and free up all RAM. Then reserve
+ * space for OS image, initrd, phys->machine table, bootstrap page table,
+ * and the bootmem bitmap.
+ * NB. There is definitely enough room for the bootmem bitmap in the
+ * bootstrap page table. We are guaranteed to get >=512kB unused 'padding'
+ * for our own use after all bootstrap elements
+ * (see asm-xen/xen-public/xen.h).
+ */
+ boot_pfn = min((int)xen_start_info.nr_pages,lmax_low_pfn);
+ bootmap_size = init_bootmem(start_pfn,boot_pfn);
+ free_bootmem(0, PFN_PHYS(boot_pfn));
+ reserve_bootmem(__pa(&_stext),
+ PFN_PHYS(start_pfn) + bootmap_size + PAGE_SIZE-1 -
+ __pa(&_stext));
+
+ /* init_bootmem() set the global max_low_pfn to boot_pfn. Now max_low_pfn
+ * can be set to the override value.
+ */
+ max_low_pfn = lmax_low_pfn;
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ if ( xen_start_info.mod_start != 0 )
+ {
+ if ( (__pa(xen_start_info.mod_start) + xen_start_info.mod_len) <=
+ (max_low_pfn << PAGE_SHIFT) )
+ {
+ initrd_start = xen_start_info.mod_start;
+ initrd_end = initrd_start + xen_start_info.mod_len;
+ initrd_below_start_ok = 1;
+ }
+ else
+ {
+ printk(KERN_ERR "initrd extends beyond end of memory "
+ "(0x%08lx > 0x%08lx)\ndisabling initrd\n",
+ __pa(xen_start_info.mod_start) + xen_start_info.mod_len,
+ max_low_pfn << PAGE_SHIFT);
+ initrd_start = 0;
+ }
+ }
+ #endif
+
+ paging_init();
+
+ /* Make sure we have a correctly sized P->M table. */
+ if ( max_pfn != xen_start_info.nr_pages )
+ {
+ phys_to_machine_mapping = alloc_bootmem_low_pages(
+ max_pfn * sizeof(unsigned long));
+ if ( max_pfn > xen_start_info.nr_pages )
+ {
+ memset(phys_to_machine_mapping, ~0,
+ max_pfn * sizeof(unsigned long));
+ memcpy(phys_to_machine_mapping,
+ (unsigned long *)xen_start_info.mfn_list,
+ xen_start_info.nr_pages * sizeof(unsigned long));
+ }
+ else
+ {
+ memcpy(phys_to_machine_mapping,
+ (unsigned long *)xen_start_info.mfn_list,
+ max_pfn * sizeof(unsigned long));
+ if (HYPERVISOR_dom_mem_op(
+ MEMOP_decrease_reservation,
+ (unsigned long *)xen_start_info.mfn_list + max_pfn,
+ xen_start_info.nr_pages - max_pfn, 0) !=
+ (xen_start_info.nr_pages - max_pfn))
+ BUG();
+ }
+ free_bootmem(__pa(xen_start_info.mfn_list),
+ PFN_PHYS(PFN_UP(xen_start_info.nr_pages *
+ sizeof(unsigned long))));
+ }
+
+ pfn_to_mfn_frame_list = alloc_bootmem_low_pages(PAGE_SIZE);
+ for ( i=0, j=0; i < max_pfn; i+=(PAGE_SIZE/sizeof(unsigned long)), j++ )
+ {
+ pfn_to_mfn_frame_list[j] =
+ virt_to_machine(&phys_to_machine_mapping[i]) >> PAGE_SHIFT;
+ }
+ HYPERVISOR_shared_info->arch.pfn_to_mfn_frame_list =
+ virt_to_machine(pfn_to_mfn_frame_list) >> PAGE_SHIFT;
+
- flush_page_update_queue();
++ op.cmd = PHYSDEVOP_SET_IOPL;
++ op.u.set_iopl.iopl = current->thread.io_pl = 1;
++ HYPERVISOR_physdev_op(&op);
+
+ if (xen_start_info.flags & SIF_INITDOMAIN )
+ {
+ if( !(xen_start_info.flags & SIF_PRIVILEGED) )
+ panic("Xen granted us console access but not privileged status");
+
+ #if defined(CONFIG_VT)
+ #if defined(CONFIG_VGA_CONSOLE)
+ conswitchp = &vga_con;
+ #elif defined(CONFIG_DUMMY_CONSOLE)
+ conswitchp = &dummy_con;
+ #endif
+ #endif
+ }
+ }
+
+ static int cachesize_override __initdata = -1;
+ static int __init cachesize_setup(char *str)
+ {
+ get_option (&str, &cachesize_override);
+ return 1;
+ }
+ __setup("cachesize=", cachesize_setup);
+
+ static int __init highio_setup(char *str)
+ {
+ printk("i386: disabling HIGHMEM block I/O\n");
+ blk_nohighio = 1;
+ return 1;
+ }
+ __setup("nohighio", highio_setup);
+
+ static int __init get_model_name(struct cpuinfo_x86 *c)
+ {
+ unsigned int *v;
+ char *p, *q;
+
+ if (cpuid_eax(0x80000000) < 0x80000004)
+ return 0;
+
+ v = (unsigned int *) c->x86_model_id;
+ cpuid(0x80000002, &v[0], &v[1], &v[2], &v[3]);
+ cpuid(0x80000003, &v[4], &v[5], &v[6], &v[7]);
+ cpuid(0x80000004, &v[8], &v[9], &v[10], &v[11]);
+ c->x86_model_id[48] = 0;
+
+ /* Intel chips right-justify this string for some dumb reason;
+ undo that brain damage */
+ p = q = &c->x86_model_id[0];
+ while ( *p == ' ' )
+ p++;
+ if ( p != q ) {
+ while ( *p )
+ *q++ = *p++;
+ while ( q <= &c->x86_model_id[48] )
+ *q++ = '\0'; /* Zero-pad the rest */
+ }
+
+ return 1;
+ }
+
+
+ static void __init display_cacheinfo(struct cpuinfo_x86 *c)
+ {
+ unsigned int n, dummy, ecx, edx, l2size;
+
+ n = cpuid_eax(0x80000000);
+
+ if (n >= 0x80000005) {
+ cpuid(0x80000005, &dummy, &dummy, &ecx, &edx);
+ printk(KERN_INFO "CPU: L1 I Cache: %dK (%d bytes/line), D cache %dK (%d bytes/line)\n",
+ edx>>24, edx&0xFF, ecx>>24, ecx&0xFF);
+ c->x86_cache_size=(ecx>>24)+(edx>>24);
+ }
+
+ if (n < 0x80000006) /* Some chips just has a large L1. */
+ return;
+
+ ecx = cpuid_ecx(0x80000006);
+ l2size = ecx >> 16;
+
+ /* AMD errata T13 (order #21922) */
+ if ((c->x86_vendor == X86_VENDOR_AMD) && (c->x86 == 6)) {
+ if (c->x86_model == 3 && c->x86_mask == 0) /* Duron Rev A0 */
+ l2size = 64;
+ if (c->x86_model == 4 &&
+ (c->x86_mask==0 || c->x86_mask==1)) /* Tbird rev A1/A2 */
+ l2size = 256;
+ }
+
+ /* Intel PIII Tualatin. This comes in two flavours.
+ * One has 256kb of cache, the other 512. We have no way
+ * to determine which, so we use a boottime override
+ * for the 512kb model, and assume 256 otherwise.
+ */
+ if ((c->x86_vendor == X86_VENDOR_INTEL) && (c->x86 == 6) &&
+ (c->x86_model == 11) && (l2size == 0))
+ l2size = 256;
+
+ if (c->x86_vendor == X86_VENDOR_CENTAUR) {
+ /* VIA C3 CPUs (670-68F) need further shifting. */
+ if ((c->x86 == 6) &&
+ ((c->x86_model == 7) || (c->x86_model == 8))) {
+ l2size >>= 8;
+ }
+
+ /* VIA also screwed up Nehemiah stepping 1, and made
+ it return '65KB' instead of '64KB'
+ - Note, it seems this may only be in engineering samples. */
+ if ((c->x86==6) && (c->x86_model==9) &&
+ (c->x86_mask==1) && (l2size==65))
+ l2size -= 1;
+ }
+
+ /* Allow user to override all this if necessary. */
+ if (cachesize_override != -1)
+ l2size = cachesize_override;
+
+ if ( l2size == 0 )
+ return; /* Again, no L2 cache is possible */
+
+ c->x86_cache_size = l2size;
+
+ printk(KERN_INFO "CPU: L2 Cache: %dK (%d bytes/line)\n",
+ l2size, ecx & 0xFF);
+ }
+
+ static void __init init_c3(struct cpuinfo_x86 *c)
+ {
+ /* Test for Centaur Extended Feature Flags presence */
+ if (cpuid_eax(0xC0000000) >= 0xC0000001) {
+ /* store Centaur Extended Feature Flags as
+ * word 5 of the CPU capability bit array
+ */
+ c->x86_capability[5] = cpuid_edx(0xC0000001);
+ }
+
+ switch (c->x86_model) {
+ case 9: /* Nehemiah */
+ default:
+ get_model_name(c);
+ display_cacheinfo(c);
+ break;
+ }
+ }
+
+ static void __init init_centaur(struct cpuinfo_x86 *c)
+ {
+ /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ 3DNow is IDd by bit 31 in extended CPUID (1*3231) anyway */
+ clear_bit(0*32+31, &c->x86_capability);
+
+ switch (c->x86) {
+ case 6:
+ init_c3(c);
+ break;
+ default:
+ panic("Unsupported Centaur CPU (%i)\n", c->x86);
+ }
+ }
+
+ static int __init init_amd(struct cpuinfo_x86 *c)
+ {
+ int r;
+
+ /* Bit 31 in normal CPUID used for nonstandard 3DNow ID;
+ 3DNow is IDd by bit 31 in extended CPUID (1*32+31) anyway */
+ clear_bit(0*32+31, &c->x86_capability);
+
+ r = get_model_name(c);
+
+ switch(c->x86)
+ {
+ case 5: /* We don't like AMD K6 */
+ panic("Unsupported AMD processor\n");
+ case 6: /* An Athlon/Duron. We can trust the BIOS probably */
+ break;
+ }
+
+ display_cacheinfo(c);
+ return r;
+ }
+
+
+ static void __init init_intel(struct cpuinfo_x86 *c)
+ {
+ char *p = NULL;
+ unsigned int l1i = 0, l1d = 0, l2 = 0, l3 = 0; /* Cache sizes */
+
+ if (c->cpuid_level > 1) {
+ /* supports eax=2 call */
+ int i, j, n;
+ int regs[4];
+ unsigned char *dp = (unsigned char *)regs;
+
+ /* Number of times to iterate */
+ n = cpuid_eax(2) & 0xFF;
+
+ for ( i = 0 ; i < n ; i++ ) {
+ cpuid(2, ®s[0], ®s[1], ®s[2], ®s[3]);
+
+ /* If bit 31 is set, this is an unknown format */
+ for ( j = 0 ; j < 3 ; j++ ) {
+ if ( regs[j] < 0 ) regs[j] = 0;
+ }
+
+ /* Byte 0 is level count, not a descriptor */
+ for ( j = 1 ; j < 16 ; j++ ) {
+ unsigned char des = dp[j];
+ unsigned char dl, dh;
+ unsigned int cs;
+
+ dh = des >> 4;
+ dl = des & 0x0F;
+
+ /* Black magic... */
+
+ switch ( dh )
+ {
+ case 0:
+ switch ( dl ) {
+ case 6:
+ /* L1 I cache */
+ l1i += 8;
+ break;
+ case 8:
+ /* L1 I cache */
+ l1i += 16;
+ break;
+ case 10:
+ /* L1 D cache */
+ l1d += 8;
+ break;
+ case 12:
+ /* L1 D cache */
+ l1d += 16;
+ break;
+ default:;
+ /* TLB, or unknown */
+ }
+ break;
+ case 2:
+ if ( dl ) {
+ /* L3 cache */
+ cs = (dl-1) << 9;
+ l3 += cs;
+ }
+ break;
+ case 4:
+ if ( c->x86 > 6 && dl ) {
+ /* P4 family */
+ /* L3 cache */
+ cs = 128 << (dl-1);
+ l3 += cs;
+ break;
+ }
+ /* else same as 8 - fall through */
+ case 8:
+ if ( dl ) {
+ /* L2 cache */
+ cs = 128 << (dl-1);
+ l2 += cs;
+ }
+ break;
+ case 6:
+ if (dl > 5) {
+ /* L1 D cache */
+ cs = 8<<(dl-6);
+ l1d += cs;
+ }
+ break;
+ case 7:
+ if ( dl >= 8 )
+ {
+ /* L2 cache */
+ cs = 64<<(dl-8);
+ l2 += cs;
+ } else {
+ /* L0 I cache, count as L1 */
+ cs = dl ? (16 << (dl-1)) : 12;
+ l1i += cs;
+ }
+ break;
+ default:
+ /* TLB, or something else we don't know about */
+ break;
+ }
+ }
+ }
+ if ( l1i || l1d )
+ printk(KERN_INFO "CPU: L1 I cache: %dK, L1 D cache: %dK\n",
+ l1i, l1d);
+ if ( l2 )
+ printk(KERN_INFO "CPU: L2 cache: %dK\n", l2);
+ if ( l3 )
+ printk(KERN_INFO "CPU: L3 cache: %dK\n", l3);
+
+ /*
+ * This assumes the L3 cache is shared; it typically lives in
+ * the northbridge. The L1 caches are included by the L2
+ * cache, and so should not be included for the purpose of
+ * SMP switching weights.
+ */
+ c->x86_cache_size = l2 ? l2 : (l1i+l1d);
+ }
+
+ /* SEP CPUID bug: Pentium Pro reports SEP but doesn't have it */
+ if ( c->x86 == 6 && c->x86_model < 3 && c->x86_mask < 3 )
+ clear_bit(X86_FEATURE_SEP, &c->x86_capability);
+
+ /* Names for the Pentium II/Celeron processors
+ detectable only by also checking the cache size.
+ Dixon is NOT a Celeron. */
+ if (c->x86 == 6) {
+ switch (c->x86_model) {
+ case 5:
+ if (l2 == 0)
+ p = "Celeron (Covington)";
+ if (l2 == 256)
+ p = "Mobile Pentium II (Dixon)";
+ break;
+
+ case 6:
+ if (l2 == 128)
+ p = "Celeron (Mendocino)";
+ break;
+
+ case 8:
+ if (l2 == 128)
+ p = "Celeron (Coppermine)";
+ break;
+ }
+ }
+
+ if ( p )
+ strcpy(c->x86_model_id, p);
+ }
+
+ void __init get_cpu_vendor(struct cpuinfo_x86 *c)
+ {
+ char *v = c->x86_vendor_id;
+
+ if (!strcmp(v, "GenuineIntel"))
+ c->x86_vendor = X86_VENDOR_INTEL;
+ else if (!strcmp(v, "AuthenticAMD"))
+ c->x86_vendor = X86_VENDOR_AMD;
+ else if (!strcmp(v, "CentaurHauls"))
+ c->x86_vendor = X86_VENDOR_CENTAUR;
+ else
+ c->x86_vendor = X86_VENDOR_UNKNOWN;
+ }
+
+ struct cpu_model_info {
+ int vendor;
+ int family;
+ char *model_names[16];
+ };
+
+ /* Naming convention should be: <Name> [(<Codename>)] */
+ /* This table only is used unless init_<vendor>() below doesn't set it; */
+ /* in particular, if CPUID levels 0x80000002..4 are supported, this isn't used */
+ static struct cpu_model_info cpu_models[] __initdata = {
+ { X86_VENDOR_INTEL, 6,
+ { "Pentium Pro A-step", "Pentium Pro", NULL, "Pentium II (Klamath)",
+ NULL, "Pentium II (Deschutes)", "Mobile Pentium II",
+ "Pentium III (Katmai)", "Pentium III (Coppermine)", NULL,
+ "Pentium III (Cascades)", NULL, NULL, NULL, NULL }},
+ { X86_VENDOR_AMD, 6, /* Is this this really necessary?? */
+ { "Athlon", "Athlon",
+ "Athlon", NULL, "Athlon", NULL,
+ NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL }}
+ };
+
+ /* Look up CPU names by table lookup. */
+ static char __init *table_lookup_model(struct cpuinfo_x86 *c)
+ {
+ struct cpu_model_info *info = cpu_models;
+ int i;
+
+ if ( c->x86_model >= 16 )
+ return NULL; /* Range check */
+
+ for ( i = 0 ; i < sizeof(cpu_models)/sizeof(struct cpu_model_info) ; i++ ) {
+ if ( info->vendor == c->x86_vendor &&
+ info->family == c->x86 ) {
+ return info->model_names[c->x86_model];
+ }
+ info++;
+ }
+ return NULL; /* Not found */
+ }
+
+
+
+ /* Standard macro to see if a specific flag is changeable */
+ static inline int flag_is_changeable_p(u32 flag)
+ {
+ u32 f1, f2;
+
+ asm("pushfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "movl %0,%1\n\t"
+ "xorl %2,%0\n\t"
+ "pushl %0\n\t"
+ "popfl\n\t"
+ "pushfl\n\t"
+ "popl %0\n\t"
+ "popfl\n\t"
+ : "=&r" (f1), "=&r" (f2)
+ : "ir" (flag));
+
+ return ((f1^f2) & flag) != 0;
+ }
+
+
+ /* Probe for the CPUID instruction */
+ static int __init have_cpuid_p(void)
+ {
+ return flag_is_changeable_p(X86_EFLAGS_ID);
+ }
+
+
+
+ #if defined(CONFIG_EDD) || defined(CONFIG_EDD_MODULE)
+ unsigned char eddnr;
+ struct edd_info edd[EDDMAXNR];
+ unsigned int edd_disk80_sig;
+ /**
+ * copy_edd() - Copy the BIOS EDD information
+ * from empty_zero_page into a safe place.
+ *
+ */
+ static inline void copy_edd(void)
+ {
+ eddnr = EDD_NR;
+ memcpy(edd, EDD_BUF, sizeof(edd));
+ edd_disk80_sig = DISK80_SIGNATURE_BUFFER;
+ }
+ #else
+ static inline void copy_edd(void) {}
+ #endif
+
+ /*
+ * This does the hard work of actually picking apart the CPU stuff...
+ */
+ void __init identify_cpu(struct cpuinfo_x86 *c)
+ {
+ int junk, i;
+ u32 xlvl, tfms;
+
+ c->loops_per_jiffy = loops_per_jiffy;
+ c->x86_cache_size = -1;
+ c->x86_vendor = X86_VENDOR_UNKNOWN;
+ c->cpuid_level = -1; /* CPUID not detected */
+ c->x86_model = c->x86_mask = 0; /* So far unknown... */
+ c->x86_vendor_id[0] = '\0'; /* Unset */
+ c->x86_model_id[0] = '\0'; /* Unset */
+ memset(&c->x86_capability, 0, sizeof c->x86_capability);
+ c->hard_math = 1;
+
+ if ( !have_cpuid_p() ) {
+ panic("Processor must support CPUID\n");
+ } else {
+ /* CPU does have CPUID */
+
+ /* Get vendor name */
+ cpuid(0x00000000, &c->cpuid_level,
+ (int *)&c->x86_vendor_id[0],
+ (int *)&c->x86_vendor_id[8],
+ (int *)&c->x86_vendor_id[4]);
+
+ get_cpu_vendor(c);
+ /* Initialize the standard set of capabilities */
+ /* Note that the vendor-specific code below might override */
+
+ /* Intel-defined flags: level 0x00000001 */
+ if ( c->cpuid_level >= 0x00000001 ) {
+ u32 capability, excap;
+ cpuid(0x00000001, &tfms, &junk, &excap, &capability);
+ c->x86_capability[0] = capability;
+ c->x86_capability[4] = excap;
+ c->x86 = (tfms >> 8) & 15;
+ c->x86_model = (tfms >> 4) & 15;
+ if (c->x86 == 0xf) {
+ c->x86 += (tfms >> 20) & 0xff;
+ c->x86_model += ((tfms >> 16) & 0xF) << 4;
+ }
+ c->x86_mask = tfms & 15;
+ } else {
+ /* Have CPUID level 0 only - unheard of */
+ c->x86 = 4;
+ }
+
+ /* AMD-defined flags: level 0x80000001 */
+ xlvl = cpuid_eax(0x80000000);
+ if ( (xlvl & 0xffff0000) == 0x80000000 ) {
+ if ( xlvl >= 0x80000001 )
+ c->x86_capability[1] = cpuid_edx(0x80000001);
+ if ( xlvl >= 0x80000004 )
+ get_model_name(c); /* Default name */
+ }
+
+ /* Transmeta-defined flags: level 0x80860001 */
+ xlvl = cpuid_eax(0x80860000);
+ if ( (xlvl & 0xffff0000) == 0x80860000 ) {
+ if ( xlvl >= 0x80860001 )
+ c->x86_capability[2] = cpuid_edx(0x80860001);
+ }
+ }
+
+ printk(KERN_DEBUG "CPU: Before vendor init, caps: %08x %08x %08x, vendor = %d\n",
+ c->x86_capability[0],
+ c->x86_capability[1],
+ c->x86_capability[2],
+ c->x86_vendor);
+
+ /*
+ * Vendor-specific initialization. In this section we
+ * canonicalize the feature flags, meaning if there are
+ * features a certain CPU supports which CPUID doesn't
+ * tell us, CPUID claiming incorrect flags, or other bugs,
+ * we handle them here.
+ *
+ * At the end of this section, c->x86_capability better
+ * indicate the features this CPU genuinely supports!
+ */
+ switch ( c->x86_vendor ) {
+ case X86_VENDOR_AMD:
+ init_amd(c);
+ break;
+
+ case X86_VENDOR_INTEL:
+ init_intel(c);
+ break;
+
+ case X86_VENDOR_CENTAUR:
+ init_centaur(c);
+ break;
+
+ default:
+ printk("Unsupported CPU vendor (%d) -- please report!\n",
+ c->x86_vendor);
+ }
+
+ printk(KERN_DEBUG "CPU: After vendor init, caps: %08x %08x %08x %08x\n",
+ c->x86_capability[0],
+ c->x86_capability[1],
+ c->x86_capability[2],
+ c->x86_capability[3]);
+
+
+ /* If the model name is still unset, do table lookup. */
+ if ( !c->x86_model_id[0] ) {
+ char *p;
+ p = table_lookup_model(c);
+ if ( p )
+ strcpy(c->x86_model_id, p);
+ else
+ /* Last resort... */
+ sprintf(c->x86_model_id, "%02x/%02x",
+ c->x86_vendor, c->x86_model);
+ }
+
+ /* Now the feature flags better reflect actual CPU features! */
+
+ printk(KERN_DEBUG "CPU: After generic, caps: %08x %08x %08x %08x\n",
+ c->x86_capability[0],
+ c->x86_capability[1],
+ c->x86_capability[2],
+ c->x86_capability[3]);
+
+ /*
+ * On SMP, boot_cpu_data holds the common feature set between
+ * all CPUs; so make sure that we indicate which features are
+ * common between the CPUs. The first time this routine gets
+ * executed, c == &boot_cpu_data.
+ */
+ if ( c != &boot_cpu_data ) {
+ /* AND the already accumulated flags with these */
+ for ( i = 0 ; i < NCAPINTS ; i++ )
+ boot_cpu_data.x86_capability[i] &= c->x86_capability[i];
+ }
+
+ printk(KERN_DEBUG "CPU: Common caps: %08x %08x %08x %08x\n",
+ boot_cpu_data.x86_capability[0],
+ boot_cpu_data.x86_capability[1],
+ boot_cpu_data.x86_capability[2],
+ boot_cpu_data.x86_capability[3]);
+ }
+
+
+ /* These need to match <asm/processor.h> */
+ static char *cpu_vendor_names[] __initdata = {
+ "Intel", "Cyrix", "AMD", "UMC", "NexGen", "Centaur", "Rise", "Transmeta" };
+
+
+ void __init print_cpu_info(struct cpuinfo_x86 *c)
+ {
+ char *vendor = NULL;
+
+ if (c->x86_vendor < sizeof(cpu_vendor_names)/sizeof(char *))
+ vendor = cpu_vendor_names[c->x86_vendor];
+ else if (c->cpuid_level >= 0)
+ vendor = c->x86_vendor_id;
+
+ if (vendor && strncmp(c->x86_model_id, vendor, strlen(vendor)))
+ printk("%s ", vendor);
+
+ if (!c->x86_model_id[0])
+ printk("%d86", c->x86);
+ else
+ printk("%s", c->x86_model_id);
+
+ if (c->x86_mask || c->cpuid_level >= 0)
+ printk(" stepping %02x\n", c->x86_mask);
+ else
+ printk("\n");
+ }
+
+ /*
+ * Get CPU information for use by the procfs.
+ */
+ static int show_cpuinfo(struct seq_file *m, void *v)
+ {
+ /*
+ * These flag bits must match the definitions in <asm/cpufeature.h>.
+ * NULL means this bit is undefined or reserved; either way it doesn't
+ * have meaning as far as Linux is concerned. Note that it's important
+ * to realize there is a difference between this table and CPUID -- if
+ * applications want to get the raw CPUID data, they should access
+ * /dev/cpu/<cpu_nr>/cpuid instead.
+ */
+ static char *x86_cap_flags[] = {
+ /* Intel-defined */
+ "fpu", "vme", "de", "pse", "tsc", "msr", "pae", "mce",
+ "cx8", "apic", NULL, "sep", "mtrr", "pge", "mca", "cmov",
+ "pat", "pse36", "pn", "clflush", NULL, "dts", "acpi", "mmx",
+ "fxsr", "sse", "sse2", "ss", "ht", "tm", "ia64", "pbe",
+
+ /* AMD-defined */
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "syscall", NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, "mp", NULL, NULL, "mmxext", NULL,
+ NULL, NULL, NULL, NULL, NULL, "lm", "3dnowext", "3dnow",
+
+ /* Transmeta-defined */
+ "recovery", "longrun", NULL, "lrti", NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* Other (Linux-defined) */
+ "cxmmx", "k6_mtrr", "cyrix_arr", "centaur_mcr",
+ NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* Intel-defined (#2) */
+ "pni", NULL, NULL, "monitor", "ds_cpl", NULL, NULL, "tm2",
+ "est", NULL, "cid", NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ /* VIA/Cyrix/Centaur-defined */
+ NULL, NULL, "xstore", NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+
+ };
+ struct cpuinfo_x86 *c = v;
+ int i, n = c - cpu_data;
+ int fpu_exception;
+
+ #ifdef CONFIG_SMP
+ if (!(cpu_online_map & (1<<n)))
+ return 0;
+ #endif
+ seq_printf(m, "processor\t: %d\n"
+ "vendor_id\t: %s\n"
+ "cpu family\t: %d\n"
+ "model\t\t: %d\n"
+ "model name\t: %s\n",
+ n,
+ c->x86_vendor_id[0] ? c->x86_vendor_id : "unknown",
+ c->x86,
+ c->x86_model,
+ c->x86_model_id[0] ? c->x86_model_id : "unknown");
+
+ if (c->x86_mask || c->cpuid_level >= 0)
+ seq_printf(m, "stepping\t: %d\n", c->x86_mask);
+ else
+ seq_printf(m, "stepping\t: unknown\n");
+
+ if ( test_bit(X86_FEATURE_TSC, &c->x86_capability) ) {
+ seq_printf(m, "cpu MHz\t\t: %lu.%03lu\n",
+ cpu_khz / 1000, (cpu_khz % 1000));
+ }
+
+ /* Cache size */
+ if (c->x86_cache_size >= 0)
+ seq_printf(m, "cache size\t: %d KB\n", c->x86_cache_size);
+
+ /* We use exception 16 if we have hardware math and we've either seen it or the CPU claims it is internal */
+ fpu_exception = c->hard_math && (ignore_irq13 || cpu_has_fpu);
+ seq_printf(m, "fdiv_bug\t: %s\n"
+ "hlt_bug\t\t: %s\n"
+ "f00f_bug\t: %s\n"
+ "coma_bug\t: %s\n"
+ "fpu\t\t: %s\n"
+ "fpu_exception\t: %s\n"
+ "cpuid level\t: %d\n"
+ "wp\t\t: %s\n"
+ "flags\t\t:",
+ c->fdiv_bug ? "yes" : "no",
+ c->hlt_works_ok ? "no" : "yes",
+ c->f00f_bug ? "yes" : "no",
+ c->coma_bug ? "yes" : "no",
+ c->hard_math ? "yes" : "no",
+ fpu_exception ? "yes" : "no",
+ c->cpuid_level,
+ c->wp_works_ok ? "yes" : "no");
+
+ for ( i = 0 ; i < 32*NCAPINTS ; i++ )
+ if ( test_bit(i, &c->x86_capability) &&
+ x86_cap_flags[i] != NULL )
+ seq_printf(m, " %s", x86_cap_flags[i]);
+
+ seq_printf(m, "\nbogomips\t: %lu.%02lu\n\n",
+ c->loops_per_jiffy/(500000/HZ),
+ (c->loops_per_jiffy/(5000/HZ)) % 100);
+ return 0;
+ }
+
+ static void *c_start(struct seq_file *m, loff_t *pos)
+ {
+ return *pos < NR_CPUS ? cpu_data + *pos : NULL;
+ }
+ static void *c_next(struct seq_file *m, void *v, loff_t *pos)
+ {
+ ++*pos;
+ return c_start(m, pos);
+ }
+ static void c_stop(struct seq_file *m, void *v)
+ {
+ }
+ struct seq_operations cpuinfo_op = {
+ start: c_start,
+ next: c_next,
+ stop: c_stop,
+ show: show_cpuinfo,
+ };
+
+ unsigned long cpu_initialized __initdata = 0;
+
+ /*
+ * cpu_init() initializes state that is per-CPU. Some data is already
+ * initialized (naturally) in the bootstrap process, such as the GDT
+ * and IDT. We reload them nevertheless, this function acts as a
+ * 'CPU state barrier', nothing should get across.
+ */
+ void __init cpu_init (void)
+ {
+ int nr = smp_processor_id();
+
+ if (test_and_set_bit(nr, &cpu_initialized)) {
+ printk(KERN_WARNING "CPU#%d already initialized!\n", nr);
+ for (;;) __sti();
+ }
+ printk(KERN_INFO "Initializing CPU#%d\n", nr);
+
+ /*
+ * set up and load the per-CPU TSS and LDT
+ */
+ atomic_inc(&init_mm.mm_count);
+ current->active_mm = &init_mm;
+ if(current->mm)
+ BUG();
+ enter_lazy_tlb(&init_mm, current, nr);
+
+ HYPERVISOR_stack_switch(__KERNEL_DS, current->thread.esp0);
+
+ load_LDT(&init_mm.context);
+
+ /* Force FPU initialization. */
+ current->flags &= ~PF_USEDFPU;
+ current->used_math = 0;
+ stts();
+ }
--- /dev/null
- mmu_update_t u;
- u.ptr = MMU_EXTENDED_COMMAND;
- u.ptr |= (unsigned long)&default_ldt[0];
- u.val = MMUEXT_SET_LDT | (5 << MMUEXT_CMD_SHIFT);
- if ( unlikely(HYPERVISOR_mmu_update(&u, 1, NULL) < 0) )
- {
- show_trace(NULL);
- panic("Failed to install default LDT");
- }
+ /*
+ * linux/arch/i386/traps.c
+ *
+ * Copyright (C) 1991, 1992 Linus Torvalds
+ *
+ * Pentium III FXSR, SSE support
+ * Gareth Hughes <gareth@valinux.com>, May 2000
+ */
+
+ /*
+ * 'Traps.c' handles hardware traps and faults after we have saved some
+ * state in 'asm.s'.
+ */
+ #include <linux/config.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/string.h>
+ #include <linux/errno.h>
+ #include <linux/ptrace.h>
+ #include <linux/timer.h>
+ #include <linux/mm.h>
+ #include <linux/init.h>
+ #include <linux/delay.h>
+ #include <linux/spinlock.h>
+ #include <linux/interrupt.h>
+ #include <linux/highmem.h>
+
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/io.h>
+ #include <asm/atomic.h>
+ #include <asm/debugreg.h>
+ #include <asm/desc.h>
+ #include <asm/i387.h>
+
+ #include <asm/smp.h>
+ #include <asm/pgalloc.h>
+
+ #include <asm/hypervisor.h>
+
+ #include <linux/irq.h>
+ #include <linux/module.h>
+
+ asmlinkage int system_call(void);
+ asmlinkage void lcall7(void);
+ asmlinkage void lcall27(void);
+
+ asmlinkage void divide_error(void);
+ asmlinkage void debug(void);
+ asmlinkage void int3(void);
+ asmlinkage void overflow(void);
+ asmlinkage void bounds(void);
+ asmlinkage void invalid_op(void);
+ asmlinkage void device_not_available(void);
+ asmlinkage void double_fault(void);
+ asmlinkage void coprocessor_segment_overrun(void);
+ asmlinkage void invalid_TSS(void);
+ asmlinkage void segment_not_present(void);
+ asmlinkage void stack_segment(void);
+ asmlinkage void general_protection(void);
+ asmlinkage void page_fault(void);
+ asmlinkage void coprocessor_error(void);
+ asmlinkage void simd_coprocessor_error(void);
+ asmlinkage void alignment_check(void);
+ asmlinkage void fixup_4gb_segment(void);
+ asmlinkage void machine_check(void);
+
+ int kstack_depth_to_print = 24;
+
+
+ /*
+ * If the address is either in the .text section of the
+ * kernel, or in the vmalloc'ed module regions, it *may*
+ * be the address of a calling routine
+ */
+
+ #ifdef CONFIG_MODULES
+
+ extern struct module *module_list;
+ extern struct module kernel_module;
+
+ static inline int kernel_text_address(unsigned long addr)
+ {
+ int retval = 0;
+ struct module *mod;
+
+ if (addr >= (unsigned long) &_stext &&
+ addr <= (unsigned long) &_etext)
+ return 1;
+
+ for (mod = module_list; mod != &kernel_module; mod = mod->next) {
+ /* mod_bound tests for addr being inside the vmalloc'ed
+ * module area. Of course it'd be better to test only
+ * for the .text subset... */
+ if (mod_bound(addr, 0, mod)) {
+ retval = 1;
+ break;
+ }
+ }
+
+ return retval;
+ }
+
+ #else
+
+ static inline int kernel_text_address(unsigned long addr)
+ {
+ return (addr >= (unsigned long) &_stext &&
+ addr <= (unsigned long) &_etext);
+ }
+
+ #endif
+
+ void show_trace(unsigned long * stack)
+ {
+ int i;
+ unsigned long addr;
+
+ if (!stack)
+ stack = (unsigned long*)&stack;
+
+ printk("Call Trace: ");
+ i = 1;
+ while (((long) stack & (THREAD_SIZE-1)) != 0) {
+ addr = *stack++;
+ if (kernel_text_address(addr)) {
+ if (i && ((i % 6) == 0))
+ printk("\n ");
+ printk("[<%08lx>] ", addr);
+ i++;
+ }
+ }
+ printk("\n");
+ }
+
+ void show_trace_task(struct task_struct *tsk)
+ {
+ unsigned long esp = tsk->thread.esp;
+
+ /* User space on another CPU? */
+ if ((esp ^ (unsigned long)tsk) & (PAGE_MASK<<1))
+ return;
+ show_trace((unsigned long *)esp);
+ }
+
+ void show_stack(unsigned long * esp)
+ {
+ unsigned long *stack;
+ int i;
+
+ // debugging aid: "show_stack(NULL);" prints the
+ // back trace for this cpu.
+
+ if(esp==NULL)
+ esp=(unsigned long*)&esp;
+
+ stack = esp;
+ for(i=0; i < kstack_depth_to_print; i++) {
+ if (((long) stack & (THREAD_SIZE-1)) == 0)
+ break;
+ if (i && ((i % 8) == 0))
+ printk("\n ");
+ printk("%08lx ", *stack++);
+ }
+ printk("\n");
+ show_trace(esp);
+ }
+
+ void show_registers(struct pt_regs *regs)
+ {
+ int in_kernel = 1;
+ unsigned long esp;
+ unsigned short ss;
+
+ esp = (unsigned long) (®s->esp);
+ ss = __KERNEL_DS;
+ if (regs->xcs & 2) {
+ in_kernel = 0;
+ esp = regs->esp;
+ ss = regs->xss & 0xffff;
+ }
+ printk(KERN_ALERT "CPU: %d\n", smp_processor_id() );
+ printk(KERN_ALERT "EIP: %04x:[<%08lx>] %s\n",
+ 0xffff & regs->xcs, regs->eip, print_tainted());
+ printk(KERN_ALERT "EFLAGS: %08lx\n",regs->eflags);
+ printk(KERN_ALERT "eax: %08lx ebx: %08lx ecx: %08lx edx: %08lx\n",
+ regs->eax, regs->ebx, regs->ecx, regs->edx);
+ printk(KERN_ALERT "esi: %08lx edi: %08lx ebp: %08lx esp: %08lx\n",
+ regs->esi, regs->edi, regs->ebp, esp);
+ printk(KERN_ALERT "ds: %04x es: %04x ss: %04x\n",
+ regs->xds & 0xffff, regs->xes & 0xffff, ss);
+ printk(KERN_ALERT "Process %s (pid: %d, stackpage=%08lx)",
+ current->comm, current->pid, 4096+(unsigned long)current);
+ /*
+ * When in-kernel, we also print out the stack and code at the
+ * time of the fault..
+ */
+ if (in_kernel) {
+
+ printk(KERN_ALERT "\nStack: ");
+ show_stack((unsigned long*)esp);
+
+ #if 0
+ {
+ int i;
+ printk(KERN_ALERT "\nCode: ");
+ if(regs->eip < PAGE_OFFSET)
+ goto bad;
+
+ for(i=0;i<20;i++)
+ {
+ unsigned char c;
+ if(__get_user(c, &((unsigned char*)regs->eip)[i])) {
+ bad:
+ printk(KERN_ALERT " Bad EIP value.");
+ break;
+ }
+ printk("%02x ", c);
+ }
+ }
+ #endif
+ }
+ printk(KERN_ALERT "\n");
+ }
+
+ spinlock_t die_lock = SPIN_LOCK_UNLOCKED;
+
+ void die(const char * str, struct pt_regs * regs, long err)
+ {
+ console_verbose();
+ spin_lock_irq(&die_lock);
+ bust_spinlocks(1);
+ printk("%s: %04lx\n", str, err & 0xffff);
+ show_registers(regs);
+ bust_spinlocks(0);
+ spin_unlock_irq(&die_lock);
+ do_exit(SIGSEGV);
+ }
+
+ static inline void die_if_kernel(const char * str, struct pt_regs * regs, long err)
+ {
+ if (!(2 & regs->xcs))
+ die(str, regs, err);
+ }
+
+
+ static void inline do_trap(int trapnr, int signr, char *str,
+ struct pt_regs * regs, long error_code,
+ siginfo_t *info)
+ {
+ if (!(regs->xcs & 2))
+ goto kernel_trap;
+
+ /*trap_signal:*/ {
+ struct task_struct *tsk = current;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = trapnr;
+ if (info)
+ force_sig_info(signr, info, tsk);
+ else
+ force_sig(signr, tsk);
+ return;
+ }
+
+ kernel_trap: {
+ unsigned long fixup = search_exception_table(regs->eip);
+ if (fixup)
+ regs->eip = fixup;
+ else
+ die(str, regs, error_code);
+ return;
+ }
+ }
+
+ #define DO_ERROR(trapnr, signr, str, name) \
+ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ do_trap(trapnr, signr, str, regs, error_code, NULL); \
+ }
+
+ #define DO_ERROR_INFO(trapnr, signr, str, name, sicode, siaddr) \
+ asmlinkage void do_##name(struct pt_regs * regs, long error_code) \
+ { \
+ siginfo_t info; \
+ info.si_signo = signr; \
+ info.si_errno = 0; \
+ info.si_code = sicode; \
+ info.si_addr = (void *)siaddr; \
+ do_trap(trapnr, signr, str, regs, error_code, &info); \
+ }
+
+ DO_ERROR_INFO( 0, SIGFPE, "divide error", divide_error, FPE_INTDIV, regs->eip)
+ DO_ERROR( 3, SIGTRAP, "int3", int3)
+ DO_ERROR( 4, SIGSEGV, "overflow", overflow)
+ DO_ERROR( 5, SIGSEGV, "bounds", bounds)
+ DO_ERROR_INFO( 6, SIGILL, "invalid operand", invalid_op, ILL_ILLOPN, regs->eip)
+ DO_ERROR( 7, SIGSEGV, "device not available", device_not_available)
+ DO_ERROR( 8, SIGSEGV, "double fault", double_fault)
+ DO_ERROR( 9, SIGFPE, "coprocessor segment overrun", coprocessor_segment_overrun)
+ DO_ERROR(10, SIGSEGV, "invalid TSS", invalid_TSS)
+ DO_ERROR(11, SIGBUS, "segment not present", segment_not_present)
+ DO_ERROR(12, SIGBUS, "stack segment", stack_segment)
+ DO_ERROR_INFO(17, SIGBUS, "alignment check", alignment_check, BUS_ADRALN, 0)
+ DO_ERROR(18, SIGBUS, "machine check", machine_check)
+
+ asmlinkage void do_general_protection(struct pt_regs * regs, long error_code)
+ {
+ /*
+ * If we trapped on an LDT access then ensure that the default_ldt is
+ * loaded, if nothing else. We load default_ldt lazily because LDT
+ * switching costs time and many applications don't need it.
+ */
+ if ( unlikely((error_code & 6) == 4) )
+ {
+ unsigned long ldt;
+ __asm__ __volatile__ ( "sldt %0" : "=r" (ldt) );
+ if ( ldt == 0 )
+ {
- HYPERVISOR_set_fast_trap(SYSCALL_VECTOR);
++ xen_set_ldt((unsigned long)&default_ldt[0], 5);
+ return;
+ }
+ }
+
+ if (!(regs->xcs & 2))
+ goto gp_in_kernel;
+
+ current->thread.error_code = error_code;
+ current->thread.trap_no = 13;
+ force_sig(SIGSEGV, current);
+ return;
+
+ gp_in_kernel:
+ {
+ unsigned long fixup;
+ fixup = search_exception_table(regs->eip);
+ if (fixup) {
+ regs->eip = fixup;
+ return;
+ }
+ die("general protection fault", regs, error_code);
+ }
+ }
+
+
+ asmlinkage void do_debug(struct pt_regs * regs, long error_code)
+ {
+ unsigned int condition;
+ struct task_struct *tsk = current;
+ siginfo_t info;
+
+ condition = HYPERVISOR_get_debugreg(6);
+
+ /* Mask out spurious debug traps due to lazy DR7 setting */
+ if (condition & (DR_TRAP0|DR_TRAP1|DR_TRAP2|DR_TRAP3)) {
+ if (!tsk->thread.debugreg[7])
+ goto clear_dr7;
+ }
+
+ /* Save debug status register where ptrace can see it */
+ tsk->thread.debugreg[6] = condition;
+
+ /* Mask out spurious TF errors due to lazy TF clearing */
+ if (condition & DR_STEP) {
+ /*
+ * The TF error should be masked out only if the current
+ * process is not traced and if the TRAP flag has been set
+ * previously by a tracing process (condition detected by
+ * the PT_DTRACE flag); remember that the i386 TRAP flag
+ * can be modified by the process itself in user mode,
+ * allowing programs to debug themselves without the ptrace()
+ * interface.
+ */
+ if ((tsk->ptrace & (PT_DTRACE|PT_PTRACED)) == PT_DTRACE)
+ goto clear_TF;
+ }
+
+ /* Ok, finally something we can handle */
+ tsk->thread.trap_no = 1;
+ tsk->thread.error_code = error_code;
+ info.si_signo = SIGTRAP;
+ info.si_errno = 0;
+ info.si_code = TRAP_BRKPT;
+
+ /* If this is a kernel mode trap, save the user PC on entry to
+ * the kernel, that's what the debugger can make sense of.
+ */
+ info.si_addr = ((regs->xcs & 2) == 0) ? (void *)tsk->thread.eip :
+ (void *)regs->eip;
+ force_sig_info(SIGTRAP, &info, tsk);
+
+ /* Disable additional traps. They'll be re-enabled when
+ * the signal is delivered.
+ */
+ clear_dr7:
+ HYPERVISOR_set_debugreg(7, 0);
+ return;
+
+ clear_TF:
+ regs->eflags &= ~TF_MASK;
+ return;
+ }
+
+
+ /*
+ * Note that we play around with the 'TS' bit in an attempt to get
+ * the correct behaviour even in the presence of the asynchronous
+ * IRQ13 behaviour
+ */
+ void math_error(void *eip)
+ {
+ struct task_struct * task;
+ siginfo_t info;
+ unsigned short cwd, swd;
+
+ /*
+ * Save the info for the exception handler and clear the error.
+ */
+ task = current;
+ save_init_fpu(task);
+ task->thread.trap_no = 16;
+ task->thread.error_code = 0;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = __SI_FAULT;
+ info.si_addr = eip;
+ /*
+ * (~cwd & swd) will mask out exceptions that are not set to unmasked
+ * status. 0x3f is the exception bits in these regs, 0x200 is the
+ * C1 reg you need in case of a stack fault, 0x040 is the stack
+ * fault bit. We should only be taking one exception at a time,
+ * so if this combination doesn't produce any single exception,
+ * then we have a bad program that isn't syncronizing its FPU usage
+ * and it will suffer the consequences since we won't be able to
+ * fully reproduce the context of the exception
+ */
+ cwd = get_fpu_cwd(task);
+ swd = get_fpu_swd(task);
+ switch (((~cwd) & swd & 0x3f) | (swd & 0x240)) {
+ case 0x000:
+ default:
+ break;
+ case 0x001: /* Invalid Op */
+ case 0x041: /* Stack Fault */
+ case 0x241: /* Stack Fault | Direction */
+ info.si_code = FPE_FLTINV;
+ break;
+ case 0x002: /* Denormalize */
+ case 0x010: /* Underflow */
+ info.si_code = FPE_FLTUND;
+ break;
+ case 0x004: /* Zero Divide */
+ info.si_code = FPE_FLTDIV;
+ break;
+ case 0x008: /* Overflow */
+ info.si_code = FPE_FLTOVF;
+ break;
+ case 0x020: /* Precision */
+ info.si_code = FPE_FLTRES;
+ break;
+ }
+ force_sig_info(SIGFPE, &info, task);
+ }
+
+ asmlinkage void do_coprocessor_error(struct pt_regs * regs, long error_code)
+ {
+ ignore_irq13 = 1;
+ math_error((void *)regs->eip);
+ }
+
+ void simd_math_error(void *eip)
+ {
+ struct task_struct * task;
+ siginfo_t info;
+ unsigned short mxcsr;
+
+ /*
+ * Save the info for the exception handler and clear the error.
+ */
+ task = current;
+ save_init_fpu(task);
+ task->thread.trap_no = 19;
+ task->thread.error_code = 0;
+ info.si_signo = SIGFPE;
+ info.si_errno = 0;
+ info.si_code = __SI_FAULT;
+ info.si_addr = eip;
+ /*
+ * The SIMD FPU exceptions are handled a little differently, as there
+ * is only a single status/control register. Thus, to determine which
+ * unmasked exception was caught we must mask the exception mask bits
+ * at 0x1f80, and then use these to mask the exception bits at 0x3f.
+ */
+ mxcsr = get_fpu_mxcsr(task);
+ switch (~((mxcsr & 0x1f80) >> 7) & (mxcsr & 0x3f)) {
+ case 0x000:
+ default:
+ break;
+ case 0x001: /* Invalid Op */
+ info.si_code = FPE_FLTINV;
+ break;
+ case 0x002: /* Denormalize */
+ case 0x010: /* Underflow */
+ info.si_code = FPE_FLTUND;
+ break;
+ case 0x004: /* Zero Divide */
+ info.si_code = FPE_FLTDIV;
+ break;
+ case 0x008: /* Overflow */
+ info.si_code = FPE_FLTOVF;
+ break;
+ case 0x020: /* Precision */
+ info.si_code = FPE_FLTRES;
+ break;
+ }
+ force_sig_info(SIGFPE, &info, task);
+ }
+
+ asmlinkage void do_simd_coprocessor_error(struct pt_regs * regs,
+ long error_code)
+ {
+ if (cpu_has_xmm) {
+ /* Handle SIMD FPU exceptions on PIII+ processors. */
+ ignore_irq13 = 1;
+ simd_math_error((void *)regs->eip);
+ } else {
+ die_if_kernel("cache flush denied", regs, error_code);
+ current->thread.trap_no = 19;
+ current->thread.error_code = error_code;
+ force_sig(SIGSEGV, current);
+ }
+ }
+
+ /*
+ * 'math_state_restore()' saves the current math information in the
+ * old math state array, and gets the new ones from the current task
+ *
+ * Careful.. There are problems with IBM-designed IRQ13 behaviour.
+ * Don't touch unless you *really* know how it works.
+ */
+ asmlinkage void math_state_restore(struct pt_regs regs)
+ {
+ /*
+ * A trap in kernel mode can be ignored. It'll be the fast XOR or
+ * copying libraries, which will correctly save/restore state and
+ * reset the TS bit in CR0.
+ */
+ if ( (regs.xcs & 2) == 0 )
+ return;
+
+ if (current->used_math) {
+ restore_fpu(current);
+ } else {
+ init_fpu();
+ }
+ current->flags |= PF_USEDFPU; /* So we fnsave on switch_to() */
+ }
+
+
+ #define _set_gate(gate_addr,type,dpl,addr) \
+ do { \
+ int __d0, __d1; \
+ __asm__ __volatile__ ("movw %%dx,%%ax\n\t" \
+ "movw %4,%%dx\n\t" \
+ "movl %%eax,%0\n\t" \
+ "movl %%edx,%1" \
+ :"=m" (*((long *) (gate_addr))), \
+ "=m" (*(1+(long *) (gate_addr))), "=&a" (__d0), "=&d" (__d1) \
+ :"i" ((short) (0x8000+(dpl<<13)+(type<<8))), \
+ "3" ((char *) (addr)),"2" (__KERNEL_CS << 16)); \
+ } while (0)
+
+ static void __init set_call_gate(void *a, void *addr)
+ {
+ _set_gate(a,12,3,addr);
+ }
+
+
+ /* NB. All these are "trap gates" (i.e. events_mask isn't cleared). */
+ static trap_info_t trap_table[] = {
+ { 0, 0, __KERNEL_CS, (unsigned long)divide_error },
+ { 1, 0, __KERNEL_CS, (unsigned long)debug },
+ { 3, 3, __KERNEL_CS, (unsigned long)int3 },
+ { 4, 3, __KERNEL_CS, (unsigned long)overflow },
+ { 5, 3, __KERNEL_CS, (unsigned long)bounds },
+ { 6, 0, __KERNEL_CS, (unsigned long)invalid_op },
+ { 7, 0, __KERNEL_CS, (unsigned long)device_not_available },
+ { 8, 0, __KERNEL_CS, (unsigned long)double_fault },
+ { 9, 0, __KERNEL_CS, (unsigned long)coprocessor_segment_overrun },
+ { 10, 0, __KERNEL_CS, (unsigned long)invalid_TSS },
+ { 11, 0, __KERNEL_CS, (unsigned long)segment_not_present },
+ { 12, 0, __KERNEL_CS, (unsigned long)stack_segment },
+ { 13, 0, __KERNEL_CS, (unsigned long)general_protection },
+ { 14, 0, __KERNEL_CS, (unsigned long)page_fault },
+ { 15, 0, __KERNEL_CS, (unsigned long)fixup_4gb_segment },
+ { 16, 0, __KERNEL_CS, (unsigned long)coprocessor_error },
+ { 17, 0, __KERNEL_CS, (unsigned long)alignment_check },
+ { 18, 0, __KERNEL_CS, (unsigned long)machine_check },
+ { 19, 0, __KERNEL_CS, (unsigned long)simd_coprocessor_error },
+ { SYSCALL_VECTOR,
+ 3, __KERNEL_CS, (unsigned long)system_call },
+ { 0, 0, 0, 0 }
+ };
+
+
+ void __init trap_init(void)
+ {
+ HYPERVISOR_set_trap_table(trap_table);
+
+ /*
+ * The default LDT is a single-entry callgate to lcall7 for iBCS and a
+ * callgate to lcall27 for Solaris/x86 binaries.
+ */
+ clear_page(&default_ldt[0]);
+ set_call_gate(&default_ldt[0],lcall7);
+ set_call_gate(&default_ldt[4],lcall27);
+ __make_page_readonly(&default_ldt[0]);
+
+ cpu_init();
+ }
--- /dev/null
- if ( flush_page_update_queue() != 0 )
- return;
-
+ /*
+ * linux/arch/i386/mm/fault.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ */
+
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/ptrace.h>
+ #include <linux/mman.h>
+ #include <linux/mm.h>
+ #include <linux/smp.h>
+ #include <linux/smp_lock.h>
+ #include <linux/interrupt.h>
+ #include <linux/init.h>
+ #include <linux/tty.h>
+ #include <linux/vt_kern.h> /* For unblank_screen() */
+
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+ #include <asm/hardirq.h>
+
+ extern void die(const char *,struct pt_regs *,long);
+
+ pgd_t *cur_pgd;
+
+ extern spinlock_t timerlist_lock;
+
+ /*
+ * Unlock any spinlocks which will prevent us from getting the
+ * message out (timerlist_lock is acquired through the
+ * console unblank code)
+ */
+ void bust_spinlocks(int yes)
+ {
+ spin_lock_init(&timerlist_lock);
+ if (yes) {
+ oops_in_progress = 1;
+ } else {
+ int loglevel_save = console_loglevel;
+ #ifdef CONFIG_VT
+ unblank_screen();
+ #endif
+ oops_in_progress = 0;
+ /*
+ * OK, the message is on the console. Now we call printk()
+ * without oops_in_progress set so that printk will give klogd
+ * a poke. Hold onto your hats...
+ */
+ console_loglevel = 15; /* NMI oopser may have shut the console up */
+ printk(" ");
+ console_loglevel = loglevel_save;
+ }
+ }
+
+ /*
+ * This routine handles page faults. It determines the address,
+ * and the problem, and then passes it off to one of the appropriate
+ * routines.
+ *
+ * error_code:
+ * bit 0 == 0 means no page found, 1 means protection fault
+ * bit 1 == 0 means read, 1 means write
+ * bit 2 == 0 means kernel, 1 means user-mode
+ */
+ asmlinkage void do_page_fault(struct pt_regs *regs,
+ unsigned long error_code,
+ unsigned long address)
+ {
+ struct task_struct *tsk = current;
+ struct mm_struct *mm;
+ struct vm_area_struct * vma;
+ unsigned long page;
+ unsigned long fixup;
+ int write;
+ siginfo_t info;
+
+ /* Set the "privileged fault" bit to something sane. */
+ error_code &= 3;
+ error_code |= (regs->xcs & 2) << 1;
+
- XEN_flush_page_update_queue(); /* flush PMD update */
+ /*
+ * We fault-in kernel-space virtual memory on-demand. The
+ * 'reference' page table is init_mm.pgd.
+ *
+ * NOTE! We MUST NOT take any locks for this case. We may
+ * be in an interrupt or a critical region, and should
+ * only copy the information from the master page table,
+ * nothing more.
+ *
+ * This verifies that the fault happens in kernel space
+ * (error_code & 4) == 0, and that the fault was not a
+ * protection error (error_code & 1) == 0.
+ */
+ if (address >= TASK_SIZE && !(error_code & 5))
+ goto vmalloc_fault;
+
+ mm = tsk->mm;
+ info.si_code = SEGV_MAPERR;
+
+ /*
+ * If we're in an interrupt or have no user
+ * context, we must not take the fault..
+ */
+ if (in_interrupt() || !mm)
+ goto no_context;
+
+ down_read(&mm->mmap_sem);
+
+ vma = find_vma(mm, address);
+ if (!vma)
+ goto bad_area;
+ if (vma->vm_start <= address)
+ goto good_area;
+ if (!(vma->vm_flags & VM_GROWSDOWN))
+ goto bad_area;
+ if (error_code & 4) {
+ /*
+ * accessing the stack below %esp is always a bug.
+ * The "+ 32" is there due to some instructions (like
+ * pusha) doing post-decrement on the stack and that
+ * doesn't show up until later..
+ */
+ if (address + 32 < regs->esp)
+ goto bad_area;
+ }
+ if (expand_stack(vma, address))
+ goto bad_area;
+ /*
+ * Ok, we have a good vm_area for this memory access, so
+ * we can handle it..
+ */
+ good_area:
+ info.si_code = SEGV_ACCERR;
+ write = 0;
+ switch (error_code & 3) {
+ default: /* 3: write, present */
+ /* fall through */
+ case 2: /* write, not present */
+ if (!(vma->vm_flags & VM_WRITE))
+ goto bad_area;
+ write++;
+ break;
+ case 1: /* read, present */
+ goto bad_area;
+ case 0: /* read, not present */
+ if (!(vma->vm_flags & (VM_READ | VM_EXEC)))
+ goto bad_area;
+ }
+
+ survive:
+ /*
+ * If for any reason at all we couldn't handle the fault,
+ * make sure we exit gracefully rather than endlessly redo
+ * the fault.
+ */
+ switch (handle_mm_fault(mm, vma, address, write)) {
+ case 1:
+ tsk->min_flt++;
+ break;
+ case 2:
+ tsk->maj_flt++;
+ break;
+ case 0:
+ goto do_sigbus;
+ default:
+ goto out_of_memory;
+ }
+
+ up_read(&mm->mmap_sem);
+ return;
+
+ /*
+ * Something tried to access memory that isn't in our memory map..
+ * Fix it, but check if it's kernel or user first..
+ */
+ bad_area:
+ up_read(&mm->mmap_sem);
+
+ /* User mode accesses just cause a SIGSEGV */
+ if (error_code & 4) {
+ tsk->thread.cr2 = address;
+ /* Kernel addresses are always protection faults */
+ tsk->thread.error_code = error_code | (address >= TASK_SIZE);
+ tsk->thread.trap_no = 14;
+ info.si_signo = SIGSEGV;
+ info.si_errno = 0;
+ /* info.si_code has been set above */
+ info.si_addr = (void *)address;
+ force_sig_info(SIGSEGV, &info, tsk);
+ return;
+ }
+
+ no_context:
+ /* Are we prepared to handle this kernel fault? */
+ if ((fixup = search_exception_table(regs->eip)) != 0) {
+ regs->eip = fixup;
+ return;
+ }
+
+ /*
+ * Oops. The kernel tried to access some bad page. We'll have to
+ * terminate things with extreme prejudice.
+ */
+
+ bust_spinlocks(1);
+
+ if (address < PAGE_SIZE)
+ printk(KERN_ALERT "Unable to handle kernel NULL pointer dereference");
+ else
+ printk(KERN_ALERT "Unable to handle kernel paging request");
+ printk(" at virtual address %08lx\n",address);
+ printk(" printing eip:\n");
+ printk("%08lx\n", regs->eip);
+ page = ((unsigned long *) cur_pgd)[address >> 22];
+ printk(KERN_ALERT "*pde=%08lx(%08lx)\n", page, machine_to_phys(page));
+ if (page & 1) {
+ page &= PAGE_MASK;
+ address &= 0x003ff000;
+ page = machine_to_phys(page);
+ page = ((unsigned long *) __va(page))[address >> PAGE_SHIFT];
+ printk(KERN_ALERT "*pte=%08lx(%08lx)\n", page,
+ machine_to_phys(page));
+ }
+ die("Oops", regs, error_code);
+ bust_spinlocks(0);
+ do_exit(SIGKILL);
+
+ /*
+ * We ran out of memory, or some other thing happened to us that made
+ * us unable to handle the page fault gracefully.
+ */
+ out_of_memory:
+ if (tsk->pid == 1) {
+ yield();
+ goto survive;
+ }
+ up_read(&mm->mmap_sem);
+ printk("VM: killing process %s\n", tsk->comm);
+ if (error_code & 4)
+ do_exit(SIGKILL);
+ goto no_context;
+
+ do_sigbus:
+ up_read(&mm->mmap_sem);
+
+ /*
+ * Send a sigbus, regardless of whether we were in kernel
+ * or user mode.
+ */
+ tsk->thread.cr2 = address;
+ tsk->thread.error_code = error_code;
+ tsk->thread.trap_no = 14;
+ info.si_signo = SIGBUS;
+ info.si_errno = 0;
+ info.si_code = BUS_ADRERR;
+ info.si_addr = (void *)address;
+ force_sig_info(SIGBUS, &info, tsk);
+
+ /* Kernel mode? Handle exceptions or die */
+ if (!(error_code & 4))
+ goto no_context;
+ return;
+
+ vmalloc_fault:
+ {
+ /*
+ * Synchronize this task's top level page-table
+ * with the 'reference' page table.
+ *
+ * Do _not_ use "tsk" here. We might be inside
+ * an interrupt in the middle of a task switch..
+ */
+ int offset = __pgd_offset(address);
+ pgd_t *pgd, *pgd_k;
+ pmd_t *pmd, *pmd_k;
+ pte_t *pte_k;
+
+ pgd = offset + cur_pgd;
+ pgd_k = init_mm.pgd + offset;
+
+ if (!pgd_present(*pgd_k))
+ goto no_context;
+ set_pgd(pgd, *pgd_k);
+
+ pmd = pmd_offset(pgd, address);
+ pmd_k = pmd_offset(pgd_k, address);
+ if (!pmd_present(*pmd_k))
+ goto no_context;
+ set_pmd(pmd, *pmd_k);
+
+ pte_k = pte_offset(pmd_k, address);
+ if (!pte_present(*pte_k))
+ goto no_context;
+ return;
+ }
+ }
--- /dev/null
- queue_l1_entry_update(pte, phys | pgprot_val(prot));
+ /*
+ * linux/arch/i386/mm/init.c
+ *
+ * Copyright (C) 1995 Linus Torvalds
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ */
+
+ #include <linux/config.h>
+ #include <linux/signal.h>
+ #include <linux/sched.h>
+ #include <linux/kernel.h>
+ #include <linux/errno.h>
+ #include <linux/string.h>
+ #include <linux/types.h>
+ #include <linux/ptrace.h>
+ #include <linux/mman.h>
+ #include <linux/mm.h>
+ #include <linux/swap.h>
+ #include <linux/smp.h>
+ #include <linux/init.h>
+ #ifdef CONFIG_BLK_DEV_INITRD
+ #include <linux/blk.h>
+ #endif
+ #include <linux/highmem.h>
+ #include <linux/pagemap.h>
+ #include <linux/bootmem.h>
+ #include <linux/slab.h>
+
+ #include <asm/processor.h>
+ #include <asm/system.h>
+ #include <asm/uaccess.h>
+ #include <asm/pgtable.h>
+ #include <asm/pgalloc.h>
+ #include <asm/dma.h>
+ #include <asm/apic.h>
+ #include <asm/tlb.h>
+
+ /* XEN: We *cannot* use mmx_clear_page() this early. Force dumb memset(). */
+ #undef clear_page
+ #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+
+ mmu_gather_t mmu_gathers[NR_CPUS];
+ unsigned long highstart_pfn, highend_pfn;
+ static unsigned long totalram_pages;
+ static unsigned long totalhigh_pages;
+
+ int do_check_pgt_cache(int low, int high)
+ {
+ int freed = 0;
+ if(pgtable_cache_size > high) {
+ do {
+ if (!QUICKLIST_EMPTY(pgd_quicklist)) {
+ free_pgd_slow(get_pgd_fast());
+ freed++;
+ }
+ if (!QUICKLIST_EMPTY(pte_quicklist)) {
+ pte_free_slow(pte_alloc_one_fast(NULL, 0));
+ freed++;
+ }
+ } while(pgtable_cache_size > low);
+ }
+ return freed;
+ }
+
+ /*
+ * NOTE: pagetable_init alloc all the fixmap pagetables contiguous on the
+ * physical space so we can cache the place of the first one and move
+ * around without checking the pgd every time.
+ */
+
+ #if CONFIG_HIGHMEM
+ pte_t *kmap_pte;
+ pgprot_t kmap_prot;
+
+ #define kmap_get_fixmap_pte(vaddr) \
+ pte_offset(pmd_offset(pgd_offset_k(vaddr), (vaddr)), (vaddr))
+
+ void __init kmap_init(void)
+ {
+ unsigned long kmap_vstart;
+
+ /* cache the first kmap pte */
+ kmap_vstart = __fix_to_virt(FIX_KMAP_BEGIN);
+ kmap_pte = kmap_get_fixmap_pte(kmap_vstart);
+
+ kmap_prot = PAGE_KERNEL;
+ }
+ #endif /* CONFIG_HIGHMEM */
+
+ void show_mem(void)
+ {
+ int i, total = 0, reserved = 0;
+ int shared = 0, cached = 0;
+ int highmem = 0;
+
+ printk("Mem-info:\n");
+ show_free_areas();
+ printk("Free swap: %6dkB\n",nr_swap_pages<<(PAGE_SHIFT-10));
+ i = max_mapnr;
+ while (i-- > 0) {
+ total++;
+ if (PageHighMem(mem_map+i))
+ highmem++;
+ if (PageReserved(mem_map+i))
+ reserved++;
+ else if (PageSwapCache(mem_map+i))
+ cached++;
+ else if (page_count(mem_map+i))
+ shared += page_count(mem_map+i) - 1;
+ }
+ printk("%d pages of RAM\n", total);
+ printk("%d pages of HIGHMEM\n",highmem);
+ printk("%d reserved pages\n",reserved);
+ printk("%d pages shared\n",shared);
+ printk("%d pages swap cached\n",cached);
+ printk("%ld pages in page table cache\n",pgtable_cache_size);
+ show_buffers();
+ }
+
+ /* References to section boundaries */
+
+ extern char _text, _etext, _edata, __bss_start, _end;
+ extern char __init_begin, __init_end;
+
+ static inline void set_pte_phys (unsigned long vaddr,
+ unsigned long phys, pgprot_t prot)
+ {
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *pte;
+
+ pgd = init_mm.pgd + __pgd_offset(vaddr);
+ if (pgd_none(*pgd)) {
+ printk("PAE BUG #00!\n");
+ return;
+ }
+ pmd = pmd_offset(pgd, vaddr);
+ if (pmd_none(*pmd)) {
+ printk("PAE BUG #01!\n");
+ return;
+ }
+ pte = pte_offset(pmd, vaddr);
+
- queue_l1_entry_update(kpte,
- (*(unsigned long *)kpte)&~_PAGE_RW);
-
++ set_pte(pte, (pte_t) { phys | pgprot_val(prot) });
+
+ /*
+ * It's enough to flush this one mapping.
+ * (PGE mappings get flushed as well)
+ */
+ __flush_tlb_one(vaddr);
+ }
+
+ void __set_fixmap(enum fixed_addresses idx, unsigned long phys,
+ pgprot_t flags)
+ {
+ unsigned long address = __fix_to_virt(idx);
+
+ if (idx >= __end_of_fixed_addresses) {
+ printk("Invalid __set_fixmap\n");
+ return;
+ }
+ set_pte_phys(address, phys, flags);
+ }
+
+ void clear_fixmap(enum fixed_addresses idx)
+ {
+ set_pte_phys(__fix_to_virt(idx), 0, __pgprot(0));
+ }
+
+ static void __init fixrange_init (unsigned long start,
+ unsigned long end, pgd_t *pgd_base)
+ {
+ pgd_t *pgd, *kpgd;
+ pmd_t *pmd, *kpmd;
+ pte_t *pte, *kpte;
+ int i, j;
+ unsigned long vaddr;
+
+ vaddr = start;
+ i = __pgd_offset(vaddr);
+ j = __pmd_offset(vaddr);
+ pgd = pgd_base + i;
+
+ for ( ; (i < PTRS_PER_PGD) && (vaddr != end); pgd++, i++) {
+ #if CONFIG_X86_PAE
+ if (pgd_none(*pgd)) {
+ pmd = (pmd_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ set_pgd(pgd, __pgd(__pa(pmd) + 0x1));
+ if (pmd != pmd_offset(pgd, 0))
+ printk("PAE BUG #02!\n");
+ }
+ pmd = pmd_offset(pgd, vaddr);
+ #else
+ pmd = (pmd_t *)pgd;
+ #endif
+ for (; (j < PTRS_PER_PMD) && (vaddr != end); pmd++, j++) {
+ if (pmd_none(*pmd)) {
+ pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ clear_page(pte);
+ kpgd = pgd_offset_k((unsigned long)pte);
+ kpmd = pmd_offset(kpgd, (unsigned long)pte);
+ kpte = pte_offset(kpmd, (unsigned long)pte);
-
- XEN_flush_page_update_queue();
++ set_pte(kpte, pte_wrprotect(*kpte));
+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte)));
+ }
+ vaddr += PMD_SIZE;
+ }
+ j = 0;
+ }
- queue_l1_entry_update(kpte,
- (*(unsigned long *)kpte)&~_PAGE_RW);
+ }
+
+
+ static void __init pagetable_init (void)
+ {
+ unsigned long vaddr, end, ram_end;
+ pgd_t *kpgd, *pgd, *pgd_base;
+ int i, j, k;
+ pmd_t *kpmd, *pmd;
+ pte_t *kpte, *pte, *pte_base;
+
+ ram_end = end = (unsigned long)__va(max_low_pfn * PAGE_SIZE);
+ if ( xen_start_info.nr_pages < max_low_pfn )
+ ram_end = (unsigned long)__va(xen_start_info.nr_pages * PAGE_SIZE);
+
+ pgd_base = init_mm.pgd;
+ i = __pgd_offset(PAGE_OFFSET);
+ pgd = pgd_base + i;
+
+ for (; i < PTRS_PER_PGD; pgd++, i++) {
+ vaddr = i*PGDIR_SIZE;
+ if (vaddr >= end)
+ break;
+ pmd = (pmd_t *)pgd;
+ for (j = 0; j < PTRS_PER_PMD; pmd++, j++) {
+ vaddr = i*PGDIR_SIZE + j*PMD_SIZE;
+ if (vaddr >= end)
+ break;
+
+ /* Filled in for us already? */
+ if ( pmd_val(*pmd) & _PAGE_PRESENT )
+ continue;
+
+ pte_base = pte = (pte_t *) alloc_bootmem_low_pages(PAGE_SIZE);
+ clear_page(pte_base);
+
+ for (k = 0; k < PTRS_PER_PTE; pte++, k++) {
+ vaddr = i*PGDIR_SIZE + j*PMD_SIZE + k*PAGE_SIZE;
+ if (vaddr >= ram_end)
+ break;
+ *pte = mk_pte_phys(__pa(vaddr), PAGE_KERNEL);
+ }
+ kpgd = pgd_offset_k((unsigned long)pte_base);
+ kpmd = pmd_offset(kpgd, (unsigned long)pte_base);
+ kpte = pte_offset(kpmd, (unsigned long)pte_base);
- XEN_flush_page_update_queue();
++ set_pte(kpte, pte_wrprotect(*kpte));
+ set_pmd(pmd, __pmd(_KERNPG_TABLE + __pa(pte_base)));
+ }
+ }
+
+ /*
+ * Fixed mappings, only the page table structure has to be
+ * created - mappings will be set by set_fixmap():
+ */
+ vaddr = __fix_to_virt(__end_of_fixed_addresses - 1) & PMD_MASK;
+ fixrange_init(vaddr, HYPERVISOR_VIRT_START, init_mm.pgd);
+
+ #if CONFIG_HIGHMEM
+ /*
+ * Permanent kmaps:
+ */
+ vaddr = PKMAP_BASE;
+ fixrange_init(vaddr, vaddr + PAGE_SIZE*LAST_PKMAP, init_mm.pgd);
+
+ pgd = init_mm.pgd + __pgd_offset(vaddr);
+ pmd = pmd_offset(pgd, vaddr);
+ pte = pte_offset(pmd, vaddr);
+ pkmap_page_table = pte;
+ #endif
+ }
+
+ static void __init zone_sizes_init(void)
+ {
+ unsigned long zones_size[MAX_NR_ZONES] = {0, 0, 0};
+ unsigned int max_dma, high, low;
+
+ max_dma = virt_to_phys((char *)MAX_DMA_ADDRESS) >> PAGE_SHIFT;
+ low = max_low_pfn;
+ high = highend_pfn;
+
+ if (low < max_dma)
+ zones_size[ZONE_DMA] = low;
+ else {
+ zones_size[ZONE_DMA] = max_dma;
+ zones_size[ZONE_NORMAL] = low - max_dma;
+ #ifdef CONFIG_HIGHMEM
+ zones_size[ZONE_HIGHMEM] = high - low;
+ #endif
+ }
+ free_area_init(zones_size);
+ }
+
+ void __init paging_init(void)
+ {
+ pagetable_init();
+
+ zone_sizes_init();
++
+ /* Switch to the real shared_info page, and clear the dummy page. */
+ set_fixmap(FIX_SHARED_INFO, xen_start_info.shared_info);
+ HYPERVISOR_shared_info = (shared_info_t *)fix_to_virt(FIX_SHARED_INFO);
+ memset(empty_zero_page, 0, sizeof(empty_zero_page));
+
+ #ifdef CONFIG_HIGHMEM
+ kmap_init();
+ #endif
+ }
+
+ static inline int page_is_ram (unsigned long pagenr)
+ {
+ return 1;
+ }
+
+ #ifdef CONFIG_HIGHMEM
+ void __init one_highpage_init(struct page *page, int free_page)
+ {
+ ClearPageReserved(page);
+ set_bit(PG_highmem, &page->flags);
+ atomic_set(&page->count, 1);
+ if ( free_page )
+ __free_page(page);
+ totalhigh_pages++;
+ }
+ #endif /* CONFIG_HIGHMEM */
+
+ static void __init set_max_mapnr_init(void)
+ {
+ #ifdef CONFIG_HIGHMEM
+ highmem_start_page = mem_map + highstart_pfn;
+ max_mapnr = num_physpages = highend_pfn;
+ num_mappedpages = max_low_pfn;
+ #else
+ max_mapnr = num_mappedpages = num_physpages = max_low_pfn;
+ #endif
+ }
+
+ static int __init free_pages_init(void)
+ {
+ #ifdef CONFIG_HIGHMEM
+ int bad_ppro = 0;
+ #endif
+ int reservedpages, pfn;
+
+ /* add only boot_pfn pages of low memory to free list.
+ * max_low_pfn may be sized for
+ * pages yet to be allocated from the hypervisor, or it may be set
+ * to override the xen_start_info amount of memory
+ */
+ int boot_pfn = min(xen_start_info.nr_pages,max_low_pfn);
+
+ /* this will put all low memory onto the freelists */
+ totalram_pages += free_all_bootmem();
+ /* XEN: init and count low-mem pages outside initial allocation. */
+ for (pfn = boot_pfn; pfn < max_low_pfn; pfn++) {
+ ClearPageReserved(&mem_map[pfn]);
+ atomic_set(&mem_map[pfn].count, 1);
+ totalram_pages++;
+ }
+
+ reservedpages = 0;
+ for (pfn = 0; pfn < boot_pfn ; pfn++) {
+ /*
+ * Only count reserved RAM pages
+ */
+ if (page_is_ram(pfn) && PageReserved(mem_map+pfn))
+ reservedpages++;
+ }
+ #ifdef CONFIG_HIGHMEM
+ for (pfn = highend_pfn-1; pfn >= highstart_pfn; pfn--)
+ one_highpage_init((struct page *) (mem_map + pfn),
+ (pfn < xen_start_info.nr_pages));
+ totalram_pages += totalhigh_pages;
+ #endif
+ return reservedpages;
+ }
+
+ void __init mem_init(void)
+ {
+ int codesize, reservedpages, datasize, initsize;
+
+ if (!mem_map)
+ BUG();
+
+ #ifdef CONFIG_HIGHMEM
+ /* check that fixmap and pkmap do not overlap */
+ if (PKMAP_BASE+LAST_PKMAP*PAGE_SIZE >= FIXADDR_START) {
+ printk(KERN_ERR "fixmap and kmap areas overlap - this will crash\n");
+ printk(KERN_ERR "pkstart: %lxh pkend: %lxh fixstart %lxh\n",
+ PKMAP_BASE, PKMAP_BASE+LAST_PKMAP*PAGE_SIZE, FIXADDR_START);
+ BUG();
+ }
+ #endif
+
+ set_max_mapnr_init();
+
+ high_memory = (void *) __va(max_low_pfn * PAGE_SIZE);
+
+ /* clear the zero-page */
+ memset(empty_zero_page, 0, PAGE_SIZE);
+
+ reservedpages = free_pages_init();
+
+ codesize = (unsigned long) &_etext - (unsigned long) &_text;
+ datasize = (unsigned long) &_edata - (unsigned long) &_etext;
+ initsize = (unsigned long) &__init_end - (unsigned long) &__init_begin;
+
+ printk(KERN_INFO "Memory: %luk/%luk available (%dk kernel code, %dk reserved, %dk data, %dk init, %ldk highmem)\n",
+ (unsigned long) nr_free_pages() << (PAGE_SHIFT-10),
+ max_mapnr << (PAGE_SHIFT-10),
+ codesize >> 10,
+ reservedpages << (PAGE_SHIFT-10),
+ datasize >> 10,
+ initsize >> 10,
+ (unsigned long) (totalhigh_pages << (PAGE_SHIFT-10))
+ );
+
+ boot_cpu_data.wp_works_ok = 1;
+ }
+
+ void free_initmem(void)
+ {
+ unsigned long addr;
+
+ addr = (unsigned long)(&__init_begin);
+ for (; addr < (unsigned long)(&__init_end); addr += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(addr));
+ set_page_count(virt_to_page(addr), 1);
+ free_page(addr);
+ totalram_pages++;
+ }
+ printk (KERN_INFO "Freeing unused kernel memory: %dk freed\n", (&__init_end - &__init_begin) >> 10);
+ }
+
+ #ifdef CONFIG_BLK_DEV_INITRD
+ void free_initrd_mem(unsigned long start, unsigned long end)
+ {
+ if (start < end)
+ printk (KERN_INFO "Freeing initrd memory: %ldk freed\n", (end - start) >> 10);
+ for (; start < end; start += PAGE_SIZE) {
+ ClearPageReserved(virt_to_page(start));
+ set_page_count(virt_to_page(start), 1);
+ free_page(start);
+ totalram_pages++;
+ }
+ }
+ #endif
+
+ void si_meminfo(struct sysinfo *val)
+ {
+ val->totalram = max_pfn;
+ val->sharedram = 0;
+ val->freeram = nr_free_pages();
+ val->bufferram = atomic_read(&buffermem_pages);
+ val->totalhigh = max_pfn-max_low_pfn;
+ val->freehigh = nr_free_highpages();
+ val->mem_unit = PAGE_SIZE;
+ return;
+ }
+
+ #if defined(CONFIG_X86_PAE)
+ struct kmem_cache_s *pae_pgd_cachep;
+ void __init pgtable_cache_init(void)
+ {
+ /*
+ * PAE pgds must be 16-byte aligned:
+ */
+ pae_pgd_cachep = kmem_cache_create("pae_pgd", 32, 0,
+ SLAB_HWCACHE_ALIGN | SLAB_MUST_HWCACHE_ALIGN, NULL, NULL);
+ if (!pae_pgd_cachep)
+ panic("init_pae(): Cannot alloc pae_pgd SLAB cache");
+ }
+ #endif /* CONFIG_X86_PAE */
--- /dev/null
- mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *w, *v;
-
- u[0].ptr = MMU_EXTENDED_COMMAND;
- u[0].val = MMUEXT_SET_FOREIGNDOM;
- u[0].val |= (unsigned long)domid << 16;
- v = w = &u[1];
+ /*
+ * arch/xen/mm/ioremap.c
+ *
+ * Re-map IO memory to kernel address space so that we can access it.
+ *
+ * (C) Copyright 1995 1996 Linus Torvalds
+ *
+ * Modifications for Xenolinux (c) 2003-2004 Keir Fraser
+ */
+
+ #include <linux/slab.h>
+ #include <linux/mm.h>
+ #include <linux/mman.h>
+ #include <linux/vmalloc.h>
+ #include <asm/io.h>
+ #include <asm/pgalloc.h>
+ #include <asm/uaccess.h>
+ #include <asm/tlb.h>
+ #include <asm/mmu.h>
+
+ #if defined(CONFIG_XEN_PRIVILEGED_GUEST)
+
+ /* These hacky macros avoid phys->machine translations. */
+ #define __direct_pte(x) ((pte_t) { (x) } )
+ #define __direct_mk_pte(page_nr,pgprot) \
+ __direct_pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
+ #define direct_mk_pte_phys(physpage, pgprot) \
+ __direct_mk_pte((physpage) >> PAGE_SHIFT, pgprot)
+
+ static inline void direct_remap_area_pte(pte_t *pte,
+ unsigned long address,
+ unsigned long size,
+ mmu_update_t **v)
+ {
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ if (address >= end)
+ BUG();
+
+ do {
+ (*v)->ptr = virt_to_machine(pte);
+ (*v)++;
+ address += PAGE_SIZE;
+ pte++;
+ } while (address && (address < end));
+ }
+
+ static inline int direct_remap_area_pmd(struct mm_struct *mm,
+ pmd_t *pmd,
+ unsigned long address,
+ unsigned long size,
+ mmu_update_t **v)
+ {
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ if (address >= end)
+ BUG();
+ do {
+ pte_t *pte = pte_alloc(mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ direct_remap_area_pte(pte, address, end - address, v);
+
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+ }
+
+ int __direct_remap_area_pages(struct mm_struct *mm,
+ unsigned long address,
+ unsigned long size,
+ mmu_update_t *v)
+ {
+ pgd_t * dir;
+ unsigned long end = address + size;
+
+ dir = pgd_offset(mm, address);
+ flush_cache_all();
+ if (address >= end)
+ BUG();
+ spin_lock(&mm->page_table_lock);
+ do {
+ pmd_t *pmd = pmd_alloc(mm, dir, address);
+ if (!pmd)
+ return -ENOMEM;
+ direct_remap_area_pmd(mm, pmd, address, end - address, &v);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+
+ } while (address && (address < end));
+ spin_unlock(&mm->page_table_lock);
+ flush_tlb_all();
+ return 0;
+ }
+
+
+ int direct_remap_area_pages(struct mm_struct *mm,
+ unsigned long address,
+ unsigned long machine_addr,
+ unsigned long size,
+ pgprot_t prot,
+ domid_t domid)
+ {
+ int i;
+ unsigned long start_address;
+ #define MAX_DIRECTMAP_MMU_QUEUE 130
- w);
++ mmu_update_t u[MAX_DIRECTMAP_MMU_QUEUE], *v = u;
+
+ start_address = address;
+
+ for( i = 0; i < size; i += PAGE_SIZE )
+ {
+ if ( (v - u) == MAX_DIRECTMAP_MMU_QUEUE )
+ {
+ /* Fill in the PTE pointers. */
+ __direct_remap_area_pages( mm,
+ start_address,
+ address-start_address,
- if ( HYPERVISOR_mmu_update(u, v - u, NULL) < 0 )
++ u);
+
- v = w;
++ if ( HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0 )
+ return -EFAULT;
- if ( v != w )
++ v = u;
+ start_address = address;
+ }
+
+ /*
+ * Fill in the machine address: PTE ptr is done later by
+ * __direct_remap_area_pages().
+ */
+ v->val = (machine_addr & PAGE_MASK) | pgprot_val(prot);
+
+ machine_addr += PAGE_SIZE;
+ address += PAGE_SIZE;
+ v++;
+ }
+
- w);
- if ( unlikely(HYPERVISOR_mmu_update(u, v - u, NULL) < 0) )
++ if ( v != u )
+ {
+ /* get the ptep's filled in */
+ __direct_remap_area_pages(mm,
+ start_address,
+ address-start_address,
++ u);
++ if ( unlikely(HYPERVISOR_mmu_update(u, v - u, NULL, domid) < 0) )
+ return -EFAULT;
+ }
+
+ return 0;
+ }
+
+
+ #endif /* CONFIG_XEN_PRIVILEGED_GUEST */
+
+
+ /*
+ * Remap an arbitrary machine address space into the kernel virtual
+ * address space. Needed when a privileged instance of Xenolinux wants
+ * to access space outside its world directly.
+ *
+ * NOTE! We need to allow non-page-aligned mappings too: we will obviously
+ * have to convert them into an offset in a page-aligned mapping, but the
+ * caller shouldn't need to know that small detail.
+ */
+ void * __ioremap(unsigned long machine_addr,
+ unsigned long size,
+ unsigned long flags)
+ {
+ #if defined(CONFIG_XEN_PRIVILEGED_GUEST)
+ void * addr;
+ struct vm_struct * area;
+ unsigned long offset, last_addr;
+ pgprot_t prot;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = machine_addr + size - 1;
+ if (!size || last_addr < machine_addr)
+ return NULL;
+
+ /* Mappings have to be page-aligned */
+ offset = machine_addr & ~PAGE_MASK;
+ machine_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr+1) - machine_addr;
+
+ /* Ok, go for it */
+ area = get_vm_area(size, VM_IOREMAP);
+ if (!area)
+ return NULL;
+ addr = area->addr;
+ prot = __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY |
+ _PAGE_ACCESSED | flags);
+ if (direct_remap_area_pages(&init_mm, VMALLOC_VMADDR(addr),
+ machine_addr, size, prot, 0)) {
+ vfree(addr);
+ return NULL;
+ }
+ return (void *) (offset + (char *)addr);
+ #else
+ return NULL;
+ #endif
+ }
+
+ void iounmap(void *addr)
+ {
+ vfree((void *)((unsigned long)addr & PAGE_MASK));
+ }
+
+ /* implementation of boot time ioremap for purpose of provising access
+ to the vga console for privileged domains. Unlike boot time ioremap on
+ other architectures, ours is permanent and not reclaimed when then vmalloc
+ infrastructure is started */
+
+ void __init *bt_ioremap(unsigned long machine_addr, unsigned long size)
+ {
+ unsigned long offset, last_addr;
+ unsigned int nrpages;
+ enum fixed_addresses idx;
+
+ /* Don't allow wraparound or zero size */
+ last_addr = machine_addr + size - 1;
+ if (!size || last_addr < machine_addr)
+ return NULL;
+
+ /*
+ * Mappings have to be page-aligned
+ */
+ offset = machine_addr & ~PAGE_MASK;
+ machine_addr &= PAGE_MASK;
+ size = PAGE_ALIGN(last_addr) - machine_addr;
+
+ /*
+ * Mappings have to fit in the FIX_BTMAP area.
+ */
+ nrpages = size >> PAGE_SHIFT;
+ if (nrpages > NR_FIX_BTMAPS)
+ return NULL;
+
+ /*
+ * Ok, go for it..
+ */
+ idx = FIX_BTMAP_BEGIN;
+ while (nrpages > 0) {
+ __set_fixmap(idx, machine_addr, PAGE_KERNEL);
+ machine_addr += PAGE_SIZE;
+ --idx;
+ --nrpages;
+ }
+
+ flush_tlb_all();
+
+ return (void*) (offset + fix_to_virt(FIX_BTMAP_BEGIN));
+ }
+
+
+ #if 0 /* We don't support these functions. They shouldn't be required. */
+ void __init bt_iounmap(void *addr, unsigned long size) {}
+ #endif
--- /dev/null
- /*
- * NB. We load the default_ldt for lcall7/27 handling on demand, as
- * it slows down context switching. Noone uses it anyway.
- */
- queue_set_ldt(0, 0);
+ #ifndef __ARCH_DESC_H
+ #define __ARCH_DESC_H
+
+ #include <asm/ldt.h>
+
+ #ifndef __ASSEMBLY__
+
+ struct desc_struct {
+ unsigned long a,b;
+ };
+
+ struct Xgt_desc_struct {
+ unsigned short size;
+ unsigned long address __attribute__((packed));
+ };
+
+ extern struct desc_struct default_ldt[];
+
+ static inline void clear_LDT(void)
+ {
- queue_set_ldt((unsigned long)segments, count);
++ xen_set_ldt(0, 0);
+ }
+
+ static inline void load_LDT(mm_context_t *pc)
+ {
+ void *segments = pc->ldt;
+ int count = pc->size;
+
+ if ( count == 0 )
+ segments = NULL;
+
++ xen_set_ldt((unsigned long)segments, count);
+ }
+
+ #endif /* __ASSEMBLY__ */
+
+ #endif /* __ARCH_DESC_H__ */
--- /dev/null
- FIX_GNTTAB,
+ /*
+ * fixmap.h: compile-time virtual memory allocation
+ *
+ * This file is subject to the terms and conditions of the GNU General Public
+ * License. See the file "COPYING" in the main directory of this archive
+ * for more details.
+ *
+ * Copyright (C) 1998 Ingo Molnar
+ *
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999
+ */
+
+ #ifndef _ASM_FIXMAP_H
+ #define _ASM_FIXMAP_H
+
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <asm/apicdef.h>
+ #include <asm/page.h>
++#include <asm-xen/gnttab.h>
+ #ifdef CONFIG_HIGHMEM
+ #include <linux/threads.h>
+ #include <asm/kmap_types.h>
+ #endif
+
+ /*
+ * Here we define all the compile-time 'special' virtual
+ * addresses. The point is to have a constant address at
+ * compile time, but to set the physical address only
+ * in the boot process. We allocate these special addresses
+ * from the end of virtual memory (0xfffff000) backwards.
+ * Also this lets us do fail-safe vmalloc(), we
+ * can guarantee that these special addresses and
+ * vmalloc()-ed addresses never overlap.
+ *
+ * these 'compile-time allocated' memory buffers are
+ * fixed-size 4k pages. (or larger if used with an increment
+ * highger than 1) use fixmap_set(idx,phys) to associate
+ * physical memory with fixmap indices.
+ *
+ * TLB entries of such buffers will not be flushed across
+ * task switches.
+ */
+
+ enum fixed_addresses {
+ #ifdef CONFIG_HIGHMEM
+ FIX_KMAP_BEGIN, /* reserved pte's for temporary kernel mappings */
+ FIX_KMAP_END = FIX_KMAP_BEGIN+(KM_TYPE_NR*NR_CPUS)-1,
+ #endif
+ FIX_BLKRING_BASE,
+ FIX_NETRING0_BASE,
+ FIX_NETRING1_BASE,
+ FIX_NETRING2_BASE,
+ FIX_NETRING3_BASE,
+ FIX_SHARED_INFO,
++ FIX_GNTTAB_BEGIN,
++ FIX_GNTTAB_END = FIX_GNTTAB_BEGIN + NR_GRANT_FRAMES - 1,
+ #ifdef CONFIG_VGA_CONSOLE
+ #define NR_FIX_BTMAPS 32 /* 128KB For the Dom0 VGA Console A0000-C0000 */
+ #else
+ #define NR_FIX_BTMAPS 1 /* in case anyone wants it in future... */
+ #endif
+ FIX_BTMAP_END,
+ FIX_BTMAP_BEGIN = FIX_BTMAP_END + NR_FIX_BTMAPS - 1,
+ /* our bt_ioremap is permanent, unlike other architectures */
+
+ __end_of_permanent_fixed_addresses,
+ __end_of_fixed_addresses = __end_of_permanent_fixed_addresses
+ };
+
+ extern void __set_fixmap (enum fixed_addresses idx,
+ unsigned long phys, pgprot_t flags);
+
+ #define set_fixmap(idx, phys) \
+ __set_fixmap(idx, phys, PAGE_KERNEL)
+ /*
+ * Some hardware wants to get fixmapped without caching.
+ */
+ #define set_fixmap_nocache(idx, phys) \
+ __set_fixmap(idx, phys, PAGE_KERNEL_NOCACHE)
+
+ extern void clear_fixmap(enum fixed_addresses idx);
+
+ /*
+ * used by vmalloc.c.
+ *
+ * Leave one empty page between vmalloc'ed areas and
+ * the start of the fixmap, and leave one page empty
+ * at the top of mem..
+ */
+ #define FIXADDR_TOP (HYPERVISOR_VIRT_START - 2*PAGE_SIZE)
+ #define __FIXADDR_SIZE (__end_of_fixed_addresses << PAGE_SHIFT)
+ #define FIXADDR_START (FIXADDR_TOP - __FIXADDR_SIZE)
+
+ #define __fix_to_virt(x) (FIXADDR_TOP - ((x) << PAGE_SHIFT))
+
+ /*
+ * 'index to address' translation. If anyone tries to use the idx
+ * directly without tranlation, we catch the bug with a NULL-deference
+ * kernel oops. Illegal ranges of incoming indices are caught too.
+ */
+ static inline unsigned long fix_to_virt(unsigned int idx)
+ {
+ return __fix_to_virt(idx);
+ }
+
+ #endif
--- /dev/null
-#ifdef CONFIG_SMP
- cpu_tlbstate[cpu].state = TLBSTATE_OK;
- cpu_tlbstate[cpu].active_mm = next;
-#endif
-
+ #ifndef __I386_MMU_CONTEXT_H
+ #define __I386_MMU_CONTEXT_H
+
+ #include <linux/config.h>
+ #include <asm/desc.h>
+ #include <asm/atomic.h>
+ #include <asm/pgalloc.h>
+
+ /*
+ * hooks to add arch specific data into the mm struct.
+ * Note that destroy_context is called even if init_new_context
+ * fails.
+ */
+ int init_new_context(struct task_struct *tsk, struct mm_struct *mm);
+ void destroy_context(struct mm_struct *mm);
+
+ #ifdef CONFIG_SMP
+
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+ {
+ if(cpu_tlbstate[cpu].state == TLBSTATE_OK)
+ cpu_tlbstate[cpu].state = TLBSTATE_LAZY;
+ }
+ #else
+ static inline void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk, unsigned cpu)
+ {
+ }
+ #endif
+
+ extern pgd_t *cur_pgd;
+
+ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next, struct task_struct *tsk, unsigned cpu)
+ {
++ struct mmuext_op _op[2], *op = _op;
+ if (prev != next) {
+ /* stop flush ipis for the previous mm */
+ clear_bit(cpu, &prev->cpu_vm_mask);
- queue_pt_switch(__pa(cur_pgd));
- /* load_LDT, if either the previous or next thread
- * has a non-default LDT.
- */
- if (next->context.size+prev->context.size)
- load_LDT(&next->context);
- }
-#ifdef CONFIG_SMP
- else {
- cpu_tlbstate[cpu].state = TLBSTATE_OK;
- if(cpu_tlbstate[cpu].active_mm != next)
- out_of_line_bug();
- if(!test_and_set_bit(cpu, &next->cpu_vm_mask)) {
- /* We were in lazy tlb mode and leave_mm disabled
- * tlb flush IPI delivery. We must reload %cr3.
- */
- cur_pgd = next->pgd;
- queue_pt_switch(__pa(cur_pgd));
- load_LDT(next);
+ /* Re-load page tables */
+ cur_pgd = next->pgd;
-#endif
++ op->cmd = MMUEXT_NEW_BASEPTR;
++ op->mfn = pfn_to_mfn(__pa(next->pgd) >> PAGE_SHIFT);
++ op++;
++ /* load_LDT, if either the previous or next thread
++ * has a non-default LDT.
++ */
++ if (next->context.size+prev->context.size) {
++ op->cmd = MMUEXT_SET_LDT;
++ op->linear_addr = (unsigned long)next->context.ldt;
++ op->nr_ents = next->context.size;
++ op++;
+ }
++ BUG_ON(HYPERVISOR_mmuext_op(_op, op-_op, NULL, DOMID_SELF));
+ }
-#define activate_mm(prev, next) \
-do { \
- switch_mm((prev),(next),NULL,smp_processor_id()); \
- flush_page_update_queue(); \
-} while ( 0 )
+ }
+
++#define activate_mm(prev, next) \
++ switch_mm((prev),(next),NULL,smp_processor_id())
+
+ #endif
--- /dev/null
-extern unsigned long *phys_to_machine_mapping;
-#define pfn_to_mfn(_pfn) (phys_to_machine_mapping[(_pfn)])
-#define mfn_to_pfn(_mfn) (machine_to_phys_mapping[(_mfn)])
+ #ifndef _I386_PAGE_H
+ #define _I386_PAGE_H
+
+ /* PAGE_SHIFT determines the page size */
+ #define PAGE_SHIFT 12
+ #define PAGE_SIZE (1UL << PAGE_SHIFT)
+ #define PAGE_MASK (~(PAGE_SIZE-1))
+
+ #ifdef __KERNEL__
+ #ifndef __ASSEMBLY__
+
+ #include <linux/config.h>
+ #include <linux/string.h>
+ #include <asm/types.h>
+ #include <asm-xen/xen-public/xen.h>
+
+ #ifdef CONFIG_XEN_SCRUB_PAGES
+ #define scrub_pages(_p,_n) memset((void *)(_p), 0, (_n) << PAGE_SHIFT)
+ #else
+ #define scrub_pages(_p,_n) ((void)0)
+ #endif
+
+ #ifdef CONFIG_X86_USE_3DNOW
+
+ #include <asm/mmx.h>
+
+ #define clear_page(page) mmx_clear_page((void *)(page))
+ #define copy_page(to,from) mmx_copy_page(to,from)
+
+ #else
+
+ /*
+ * On older X86 processors its not a win to use MMX here it seems.
+ * Maybe the K6-III ?
+ */
+
+ #define clear_page(page) memset((void *)(page), 0, PAGE_SIZE)
+ #define copy_page(to,from) memcpy((void *)(to), (void *)(from), PAGE_SIZE)
+
+ #endif
+
+ #define clear_user_page(page, vaddr) clear_page(page)
+ #define copy_user_page(to, from, vaddr) copy_page(to, from)
+
+ /**** MACHINE <-> PHYSICAL CONVERSION MACROS ****/
- if ( (ret & 1) ) ret = machine_to_phys(ret);
++extern unsigned int *phys_to_machine_mapping;
++#define pfn_to_mfn(_pfn) ((unsigned long)(phys_to_machine_mapping[(_pfn)]))
++#define mfn_to_pfn(_mfn) ((unsigned long)(machine_to_phys_mapping[(_mfn)]))
+ static inline unsigned long phys_to_machine(unsigned long phys)
+ {
+ unsigned long machine = pfn_to_mfn(phys >> PAGE_SHIFT);
+ machine = (machine << PAGE_SHIFT) | (phys & ~PAGE_MASK);
+ return machine;
+ }
+ static inline unsigned long machine_to_phys(unsigned long machine)
+ {
+ unsigned long phys = mfn_to_pfn(machine >> PAGE_SHIFT);
+ phys = (phys << PAGE_SHIFT) | (machine & ~PAGE_MASK);
+ return phys;
+ }
+
+ /*
+ * These are used to make use of C type-checking..
+ */
+ #if CONFIG_X86_PAE
+ typedef struct { unsigned long pte_low, pte_high; } pte_t;
+ typedef struct { unsigned long long pmd; } pmd_t;
+ typedef struct { unsigned long long pgd; } pgd_t;
+ #define pte_val(x) ((x).pte_low | ((unsigned long long)(x).pte_high << 32))
+ #else
+ typedef struct { unsigned long pte_low; } pte_t;
+ typedef struct { unsigned long pmd; } pmd_t;
+ typedef struct { unsigned long pgd; } pgd_t;
+ static inline unsigned long pte_val(pte_t x)
+ {
+ unsigned long ret = x.pte_low;
+ if ( (ret & 1) ) ret = machine_to_phys(ret);
+ return ret;
+ }
+ #define pte_val_ma(x) ((x).pte_low)
+ #endif
+ #define PTE_MASK PAGE_MASK
+
+ typedef struct { unsigned long pgprot; } pgprot_t;
+
+ static inline unsigned long pmd_val(pmd_t x)
+ {
+ unsigned long ret = x.pmd;
-static inline pte_t __pte(unsigned long x)
-{
- if ( (x & 1) ) x = phys_to_machine(x);
- return ((pte_t) { (x) });
-}
-static inline pmd_t __pmd(unsigned long x)
-{
- if ( (x & 1) ) x = phys_to_machine(x);
- return ((pmd_t) { (x) });
-}
++ if ( ret ) ret = machine_to_phys(ret) | 1;
+ return ret;
+ }
++#define pmd_val_ma(x) ((x).pmd)
+ #define pgd_val(x) ({ BUG(); (unsigned long)0; })
+ #define pgprot_val(x) ((x).pgprot)
+
++#define __pte(x) ({ unsigned long _x = (x); \
++ (((_x)&1) ? ((pte_t) {phys_to_machine(_x)}) : ((pte_t) {(_x)})); })
++#define __pte_ma(x) ((pte_t) { (x) } )
++#define __pmd(x) ({ unsigned long _x = (x); \
++ (((_x)&1) ? ((pmd_t) {phys_to_machine(_x)}) : ((pmd_t) {(_x)})); })
+ #define __pgd(x) ({ BUG(); (pgprot_t) { 0 }; })
+ #define __pgprot(x) ((pgprot_t) { (x) } )
+
+ #endif /* !__ASSEMBLY__ */
+
+ /* to align the pointer to the (next) page boundary */
+ #define PAGE_ALIGN(addr) (((addr)+PAGE_SIZE-1)&PAGE_MASK)
+
+ /*
+ * This handles the memory map.. We could make this a config
+ * option, but too many people screw it up, and too few need
+ * it.
+ *
+ * A __PAGE_OFFSET of 0xC0000000 means that the kernel has
+ * a virtual address space of one gigabyte, which limits the
+ * amount of physical memory you can use to about 950MB.
+ *
+ * If you want more physical memory than this then see the CONFIG_HIGHMEM4G
+ * and CONFIG_HIGHMEM64G options in the kernel configuration.
+ */
+
+ #define __PAGE_OFFSET (0xC0000000)
+
+ #ifndef __ASSEMBLY__
+
+ /*
+ * Tell the user there is some problem. Beep too, so we can
+ * see^H^H^Hhear bugs in early bootup as well!
+ * The offending file and line are encoded after the "officially
+ * undefined" opcode for parsing in the trap handler.
+ */
+
+ #if 1 /* Set to zero for a slightly smaller kernel */
+ #define BUG() \
+ __asm__ __volatile__( "ud2\n" \
+ "\t.word %c0\n" \
+ "\t.long %c1\n" \
+ : : "i" (__LINE__), "i" (__FILE__))
+ #else
+ #define BUG() __asm__ __volatile__("ud2\n")
+ #endif
+
+ #define PAGE_BUG(page) do { \
+ BUG(); \
+ } while (0)
+
+ /* Pure 2^n version of get_order */
+ static __inline__ int get_order(unsigned long size)
+ {
+ int order;
+
+ size = (size-1) >> (PAGE_SHIFT-1);
+ order = -1;
+ do {
+ size >>= 1;
+ order++;
+ } while (size);
+ return order;
+ }
+
+ #endif /* __ASSEMBLY__ */
+
+ #define PAGE_OFFSET ((unsigned long)__PAGE_OFFSET)
+ #define __pa(x) ((unsigned long)(x)-PAGE_OFFSET)
+ #define __va(x) ((void *)((unsigned long)(x)+PAGE_OFFSET))
+ #define virt_to_page(kaddr) (mem_map + (__pa(kaddr) >> PAGE_SHIFT))
+ #define VALID_PAGE(page) ((page - mem_map) < max_mapnr)
+
+ #define VM_DATA_DEFAULT_FLAGS (VM_READ | VM_WRITE | VM_EXEC | \
+ VM_MAYREAD | VM_MAYWRITE | VM_MAYEXEC)
+
+ /* VIRT <-> MACHINE conversion */
+ #define virt_to_machine(_a) (phys_to_machine(__pa(_a)))
+ #define machine_to_virt(_m) (__va(machine_to_phys(_m)))
+
+ #endif /* __KERNEL__ */
+
+ #endif /* _I386_PAGE_H */
--- /dev/null
- XEN_flush_page_update_queue(); \
+ #ifndef _I386_PGALLOC_H
+ #define _I386_PGALLOC_H
+
+ #include <linux/config.h>
+ #include <asm/processor.h>
+ #include <asm/fixmap.h>
+ #include <asm/hypervisor.h>
+ #include <linux/threads.h>
+
+ /*
+ * Quick lists are aligned so that least significant bits of array pointer
+ * are all zero when list is empty, and all one when list is full.
+ */
+ #define QUICKLIST_ENTRIES 256
+ #define QUICKLIST_EMPTY(_l) !((unsigned long)(_l) & ((QUICKLIST_ENTRIES*4)-1))
+ #define QUICKLIST_FULL(_l) QUICKLIST_EMPTY((_l)+1)
+ #define pgd_quicklist (current_cpu_data.pgd_quick)
+ #define pmd_quicklist (current_cpu_data.pmd_quick)
+ #define pte_quicklist (current_cpu_data.pte_quick)
+ #define pgtable_cache_size (current_cpu_data.pgtable_cache_sz)
+
+ #define pmd_populate(mm, pmd, pte) \
+ do { \
+ set_pmd(pmd, __pmd(_PAGE_TABLE + __pa(pte))); \
- __make_page_readonly(pgd);
- queue_pgd_pin(__pa(pgd));
+ } while ( 0 )
+
+ /*
+ * Allocate and free page tables.
+ */
+
+ #if defined (CONFIG_X86_PAE)
+
+ #error "no PAE support as yet"
+
+ /*
+ * We can't include <linux/slab.h> here, thus these uglinesses.
+ */
+ struct kmem_cache_s;
+
+ extern struct kmem_cache_s *pae_pgd_cachep;
+ extern void *kmem_cache_alloc(struct kmem_cache_s *, int);
+ extern void kmem_cache_free(struct kmem_cache_s *, void *);
+
+
+ static inline pgd_t *get_pgd_slow(void)
+ {
+ int i;
+ pgd_t *pgd = kmem_cache_alloc(pae_pgd_cachep, GFP_KERNEL);
+
+ if (pgd) {
+ for (i = 0; i < USER_PTRS_PER_PGD; i++) {
+ unsigned long pmd = __get_free_page(GFP_KERNEL);
+ if (!pmd)
+ goto out_oom;
+ clear_page(pmd);
+ set_pgd(pgd + i, __pgd(1 + __pa(pmd)));
+ }
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ init_mm.pgd + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
+ }
+ return pgd;
+ out_oom:
+ for (i--; i >= 0; i--)
+ free_page((unsigned long)__va(pgd_val(pgd[i])-1));
+ kmem_cache_free(pae_pgd_cachep, pgd);
+ return NULL;
+ }
+
+ #else
+
+ static inline pgd_t *get_pgd_slow(void)
+ {
+ pgd_t *pgd = (pgd_t *)__get_free_page(GFP_KERNEL);
+
+ if (pgd) {
+ memset(pgd, 0, USER_PTRS_PER_PGD * sizeof(pgd_t));
+ memcpy(pgd + USER_PTRS_PER_PGD,
+ init_mm.pgd + USER_PTRS_PER_PGD,
+ (PTRS_PER_PGD - USER_PTRS_PER_PGD) * sizeof(pgd_t));
- queue_pgd_unpin(__pa(pgd));
- __make_page_writable(pgd);
++ __make_page_readonly(pgd);
++ xen_pgd_pin(__pa(pgd));
+ }
+ return pgd;
+ }
+
+ #endif /* CONFIG_X86_PAE */
+
+ static inline pgd_t *get_pgd_fast(void)
+ {
+ unsigned long ret;
+
+ if ( !QUICKLIST_EMPTY(pgd_quicklist) ) {
+ ret = *(--pgd_quicklist);
+ pgtable_cache_size--;
+
+ } else
+ ret = (unsigned long)get_pgd_slow();
+ return (pgd_t *)ret;
+ }
+
+ static inline void free_pgd_slow(pgd_t *pgd)
+ {
+ #if defined(CONFIG_X86_PAE)
+ #error
+ int i;
+
+ for (i = 0; i < USER_PTRS_PER_PGD; i++)
+ free_page((unsigned long)__va(pgd_val(pgd[i])-1));
+ kmem_cache_free(pae_pgd_cachep, pgd);
+ #else
- queue_pte_pin(__pa(pte));
++ xen_pgd_unpin(__pa(pgd));
++ __make_page_writable(pgd);
+ free_page((unsigned long)pgd);
+ #endif
+ }
+
+ static inline void free_pgd_fast(pgd_t *pgd)
+ {
+ if ( !QUICKLIST_FULL(pgd_quicklist) ) {
+ *(pgd_quicklist++) = (unsigned long)pgd;
+ pgtable_cache_size++;
+ } else
+ free_pgd_slow(pgd);
+ }
+
+ static inline pte_t *pte_alloc_one(struct mm_struct *mm, unsigned long address)
+ {
+ pte_t *pte;
+
+ pte = (pte_t *) __get_free_page(GFP_KERNEL);
+ if (pte)
+ {
+ clear_page(pte);
+ __make_page_readonly(pte);
- queue_pte_unpin(__pa(pte));
++ xen_pte_pin(__pa(pte));
+ }
+ return pte;
+
+ }
+
+ static inline pte_t *pte_alloc_one_fast(struct mm_struct *mm,
+ unsigned long address)
+ {
+ unsigned long ret = 0;
+ if ( !QUICKLIST_EMPTY(pte_quicklist) ) {
+ ret = *(--pte_quicklist);
+ pgtable_cache_size--;
+ }
+ return (pte_t *)ret;
+ }
+
+ static __inline__ void pte_free_slow(pte_t *pte)
+ {
- if (mm == current->active_mm) queue_tlb_flush();
- XEN_flush_page_update_queue();
++ xen_pte_unpin(__pa(pte));
+ __make_page_writable(pte);
+ free_page((unsigned long)pte);
+ }
+
+ static inline void pte_free_fast(pte_t *pte)
+ {
+ if ( !QUICKLIST_FULL(pte_quicklist) ) {
+ *(pte_quicklist++) = (unsigned long)pte;
+ pgtable_cache_size++;
+ } else
+ pte_free_slow(pte);
+ }
+
+ #define pte_free(pte) pte_free_fast(pte)
+ #define pgd_free(pgd) free_pgd_fast(pgd)
+ #define pgd_alloc(mm) get_pgd_fast()
+
+ /*
+ * allocating and freeing a pmd is trivial: the 1-entry pmd is
+ * inside the pgd, so has no extra memory associated with it.
+ * (In the PAE case we free the pmds as part of the pgd.)
+ */
+
+ #define pmd_alloc_one_fast(mm, addr) ({ BUG(); ((pmd_t *)1); })
+ #define pmd_alloc_one(mm, addr) ({ BUG(); ((pmd_t *)2); })
+ #define pmd_free_slow(x) do { } while (0)
+ #define pmd_free_fast(x) do { } while (0)
+ #define pmd_free(x) do { } while (0)
+ #define pgd_populate(mm, pmd, pte) BUG()
+
+ extern int do_check_pgt_cache(int, int);
+
+ /*
+ * TLB flushing:
+ *
+ * - flush_tlb() flushes the current mm struct TLBs
+ * - flush_tlb_all() flushes all processes TLBs
+ * - flush_tlb_mm(mm) flushes the specified mm context TLB's
+ * - flush_tlb_page(vma, vmaddr) flushes one page
+ * - flush_tlb_range(mm, start, end) flushes a range of pages
+ * - flush_tlb_pgtables(mm, start, end) flushes a range of page tables
+ *
+ * ..but the i386 has somewhat limited tlb flushing capabilities,
+ * and page-granular flushes are available only on i486 and up.
+ */
+
+ #ifndef CONFIG_SMP
+
+ #define flush_tlb() __flush_tlb()
+ #define flush_tlb_all() __flush_tlb_all()
+ #define local_flush_tlb() __flush_tlb()
+
+ static inline void flush_tlb_mm(struct mm_struct *mm)
+ {
- if (vma->vm_mm == current->active_mm) queue_invlpg(addr);
- XEN_flush_page_update_queue();
++ if (mm == current->active_mm) xen_tlb_flush();
+ }
+
+ static inline void flush_tlb_page(struct vm_area_struct *vma,
+ unsigned long addr)
+ {
- if (mm == current->active_mm) queue_tlb_flush();
- XEN_flush_page_update_queue();
++ if (vma->vm_mm == current->active_mm) xen_invlpg(addr);
+ }
+
+ static inline void flush_tlb_range(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+ {
-#error no guestos SMP support yet...
++ if (mm == current->active_mm) xen_tlb_flush();
+ }
+
+ #else
- XEN_flush_page_update_queue();
++#error no kernel SMP support yet...
+ #include <asm/smp.h>
+
+ #define local_flush_tlb() \
+ __flush_tlb()
+
+ extern void flush_tlb_all(void);
+ extern void flush_tlb_current_task(void);
+ extern void flush_tlb_mm(struct mm_struct *);
+ extern void flush_tlb_page(struct vm_area_struct *, unsigned long);
+
+ #define flush_tlb() flush_tlb_current_task()
+
+ static inline void flush_tlb_range(struct mm_struct * mm, unsigned long start, unsigned long end)
+ {
+ flush_tlb_mm(mm);
+ }
+
+ #define TLBSTATE_OK 1
+ #define TLBSTATE_LAZY 2
+
+ struct tlb_state
+ {
+ struct mm_struct *active_mm;
+ int state;
+ } ____cacheline_aligned;
+ extern struct tlb_state cpu_tlbstate[NR_CPUS];
+
+ #endif /* CONFIG_SMP */
+
+ static inline void flush_tlb_pgtables(struct mm_struct *mm,
+ unsigned long start, unsigned long end)
+ {
+ /* i386 does not keep any page table caches in TLB */
+ }
+
+ /*
+ * NB. The 'domid' field should be zero if mapping I/O space (non RAM).
+ * Otherwise it identifies the owner of the memory that is being mapped.
+ */
+ extern int direct_remap_area_pages(struct mm_struct *mm,
+ unsigned long address,
+ unsigned long machine_addr,
+ unsigned long size,
+ pgprot_t prot,
+ domid_t domid);
+
+ extern int __direct_remap_area_pages(struct mm_struct *mm,
+ unsigned long address,
+ unsigned long size,
+ mmu_update_t *v);
+
+
+
+ #endif /* _I386_PGALLOC_H */
--- /dev/null
-#define set_pte(pteptr, pteval) queue_l1_entry_update(pteptr, (pteval).pte_low)
-#define set_pte_atomic(pteptr, pteval) queue_l1_entry_update(pteptr, (pteval).pte_low)
-#define set_pmd(pmdptr, pmdval) queue_l2_entry_update((pmdptr), (pmdval))
+ #ifndef _I386_PGTABLE_2LEVEL_H
+ #define _I386_PGTABLE_2LEVEL_H
+
+ /*
+ * traditional i386 two-level paging structure:
+ */
+
+ #define PGDIR_SHIFT 22
+ #define PTRS_PER_PGD 1024
+
+ /*
+ * the i386 is two-level, so we don't really have any
+ * PMD directory physically.
+ */
+ #define PMD_SHIFT 22
+ #define PTRS_PER_PMD 1
+
+ #define PTRS_PER_PTE 1024
+
+ #define pte_ERROR(e) \
+ printk("%s:%d: bad pte %08lx.\n", __FILE__, __LINE__, (e).pte_low)
+ #define pmd_ERROR(e) \
+ printk("%s:%d: bad pmd %08lx.\n", __FILE__, __LINE__, pmd_val(e))
+ #define pgd_ERROR(e) \
+ printk("%s:%d: bad pgd %08lx.\n", __FILE__, __LINE__, pgd_val(e))
+
+ /*
+ * The "pgd_xxx()" functions here are trivial for a folded two-level
+ * setup: the pgd is never bad, and a pmd always exists (as it's folded
+ * into the pgd entry)
+ */
+ static inline int pgd_none(pgd_t pgd) { return 0; }
+ static inline int pgd_bad(pgd_t pgd) { return 0; }
+ static inline int pgd_present(pgd_t pgd) { return 1; }
+ #define pgd_clear(xp) do { } while (0)
+
-#define INVALID_P2M_ENTRY (~0UL)
++/*
++ * Certain architectures need to do special things when PTEs
++ * within a page table are directly modified. Thus, the following
++ * hook is made available.
++ */
++#define set_pte(pteptr, pteval) (*(pteptr) = pteval)
++#define set_pte_atomic(pteptr, pteval) (*(pteptr) = pteval)
++
++/*
++ * (pmds are folded into pgds so this doesnt get actually called,
++ * but the define is needed for a generic inline function.)
++ */
++#define set_pmd(pmdptr, pmdval) xen_l2_entry_update((pmdptr), (pmdval))
+ #define set_pgd(pgdptr, pgdval) ((void)0)
+
+ #define pgd_page(pgd) \
+ ((unsigned long) __va(pgd_val(pgd) & PAGE_MASK))
+
+ static inline pmd_t * pmd_offset(pgd_t * dir, unsigned long address)
+ {
+ return (pmd_t *) dir;
+ }
+
++#define ptep_get_and_clear(xp) __pte_ma(xchg(&(xp)->pte_low, 0))
+ #define pte_same(a, b) ((a).pte_low == (b).pte_low)
+
+ /*
+ * We detect special mappings in one of two ways:
+ * 1. If the MFN is an I/O page then Xen will set the m2p entry
+ * to be outside our maximum possible pseudophys range.
+ * 2. If the MFN belongs to a different domain then we will certainly
+ * not have MFN in our p2m table. Conversely, if the page is ours,
+ * then we'll have p2m(m2p(MFN))==MFN.
+ * If we detect a special mapping then it doesn't have a 'struct page'.
+ * We force !VALID_PAGE() by returning an out-of-range pointer.
+ *
+ * NB. These checks require that, for any MFN that is not in our reservation,
+ * there is no PFN such that p2m(PFN) == MFN. Otherwise we can get confused if
+ * we are foreign-mapping the MFN, and the other domain as m2p(MFN) == PFN.
+ * Yikes! Various places must poke in INVALID_P2M_ENTRY for safety.
+ *
+ * NB2. When deliberately mapping foreign pages into the p2m table, you *must*
+ * use FOREIGN_FRAME(). This will cause pte_pfn() to choke on it, as we
+ * require. In all the cases we care about, the high bit gets shifted out
+ * (e.g., phys_to_machine()) so behaviour there is correct.
+ */
-/*
- * A note on implementation of this atomic 'get-and-clear' operation.
- * This is actually very simple because XenoLinux can only run on a single
- * processor. Therefore, we cannot race other processors setting the 'accessed'
- * or 'dirty' bits on a page-table entry.
- * Even if pages are shared between domains, that is not a problem because
- * each domain will have separate page tables, with their own versions of
- * accessed & dirty state.
- */
-static inline pte_t ptep_get_and_clear(pte_t *xp)
-{
- pte_t pte = *xp;
- if ( !pte_none(pte) )
- queue_l1_entry_update(xp, 0);
- return pte;
-}
-
++#define INVALID_P2M_ENTRY (~0U)
+ #define FOREIGN_FRAME(_m) ((_m) | (1UL<<((sizeof(unsigned long)*8)-1)))
+ #define pte_page(_pte) \
+ ({ \
+ unsigned long mfn = (_pte).pte_low >> PAGE_SHIFT; \
+ unsigned long pfn = mfn_to_pfn(mfn); \
+ if ( (pfn >= max_mapnr) || (pfn_to_mfn(pfn) != mfn) ) \
+ pfn = max_mapnr; /* specia: force !VALID_PAGE() */ \
+ &mem_map[pfn]; \
+ })
+
+ #define pte_none(x) (!(x).pte_low)
+ #define __mk_pte(page_nr,pgprot) __pte(((page_nr) << PAGE_SHIFT) | pgprot_val(pgprot))
+
+ #endif /* _I386_PGTABLE_2LEVEL_H */
--- /dev/null
-#define __flush_tlb() ({ queue_tlb_flush(); XEN_flush_page_update_queue(); })
+ #ifndef _I386_PGTABLE_H
+ #define _I386_PGTABLE_H
+
+ #include <linux/config.h>
+
+ /*
+ * The Linux memory management assumes a three-level page table setup. On
+ * the i386, we use that, but "fold" the mid level into the top-level page
+ * table, so that we physically have the same two-level page table as the
+ * i386 mmu expects.
+ *
+ * This file contains the functions and defines necessary to modify and use
+ * the i386 page table tree.
+ */
+ #ifndef __ASSEMBLY__
+ #include <asm/processor.h>
+ #include <asm/hypervisor.h>
+ #include <linux/threads.h>
+ #include <asm/fixmap.h>
+
+ #ifndef _I386_BITOPS_H
+ #include <asm/bitops.h>
+ #endif
+
+ #define swapper_pg_dir 0
+ extern void paging_init(void);
+
+ /* Caches aren't brain-dead on the intel. */
+ #define flush_cache_all() do { } while (0)
+ #define flush_cache_mm(mm) do { } while (0)
+ #define flush_cache_range(mm, start, end) do { } while (0)
+ #define flush_cache_page(vma, vmaddr) do { } while (0)
+ #define flush_page_to_ram(page) do { } while (0)
+ #define flush_dcache_page(page) do { } while (0)
+ #define flush_icache_range(start, end) do { } while (0)
+ #define flush_icache_page(vma,pg) do { } while (0)
+ #define flush_icache_user_range(vma,pg,adr,len) do { } while (0)
+
+ extern unsigned long pgkern_mask;
+
-#define __flush_tlb_one(addr) ({ queue_invlpg(addr); XEN_flush_page_update_queue(); })
-#define __flush_tlb_single(addr) ({ queue_invlpg(addr); XEN_flush_page_update_queue(); })
++#define __flush_tlb() xen_tlb_flush()
+ #define __flush_tlb_global() __flush_tlb()
+ #define __flush_tlb_all() __flush_tlb_global()
-#define pte_clear(xp) queue_l1_entry_update(xp, 0)
++#define __flush_tlb_one(addr) xen_invlpg(addr)
++#define __flush_tlb_single(addr) xen_invlpg(addr)
+
+ /*
+ * ZERO_PAGE is a global shared page that is always zero: used
+ * for zero-mapped memory areas etc..
+ */
+ extern unsigned long empty_zero_page[1024];
+ #define ZERO_PAGE(vaddr) (virt_to_page(empty_zero_page))
+
+ #endif /* !__ASSEMBLY__ */
+
+ /*
+ * The Linux x86 paging architecture is 'compile-time dual-mode', it
+ * implements both the traditional 2-level x86 page tables and the
+ * newer 3-level PAE-mode page tables.
+ */
+ #ifndef __ASSEMBLY__
+ #if CONFIG_X86_PAE
+ # include <asm/pgtable-3level.h>
+
+ /*
+ * Need to initialise the X86 PAE caches
+ */
+ extern void pgtable_cache_init(void);
+
+ #else
+ # include <asm/pgtable-2level.h>
+
+ /*
+ * No page table caches to initialise
+ */
+ #define pgtable_cache_init() do { } while (0)
+
+ #endif
+ #endif
+
+ #define PMD_SIZE (1UL << PMD_SHIFT)
+ #define PMD_MASK (~(PMD_SIZE-1))
+ #define PGDIR_SIZE (1UL << PGDIR_SHIFT)
+ #define PGDIR_MASK (~(PGDIR_SIZE-1))
+
+ #define USER_PTRS_PER_PGD (TASK_SIZE/PGDIR_SIZE)
+ #define FIRST_USER_PGD_NR 0
+
+ #define USER_PGD_PTRS (PAGE_OFFSET >> PGDIR_SHIFT)
+ #define KERNEL_PGD_PTRS (PTRS_PER_PGD-USER_PGD_PTRS)
+
+ #define TWOLEVEL_PGDIR_SHIFT 22
+ #define BOOT_USER_PGD_PTRS (__PAGE_OFFSET >> TWOLEVEL_PGDIR_SHIFT)
+ #define BOOT_KERNEL_PGD_PTRS (1024-BOOT_USER_PGD_PTRS)
+
+
+ #ifndef __ASSEMBLY__
+ /* 4MB is just a nice "safety zone". Also, we align to a fresh pde. */
+ #define VMALLOC_OFFSET (4*1024*1024)
+ extern void * high_memory;
+ #define VMALLOC_START (((unsigned long) high_memory + 2*VMALLOC_OFFSET-1) & \
+ ~(VMALLOC_OFFSET-1))
+ #define VMALLOC_VMADDR(x) ((unsigned long)(x))
+ #if CONFIG_HIGHMEM
+ # define VMALLOC_END (PKMAP_BASE-2*PAGE_SIZE)
+ #else
+ # define VMALLOC_END (FIXADDR_START-2*PAGE_SIZE)
+ #endif
+
+ #define _PAGE_BIT_PRESENT 0
+ #define _PAGE_BIT_RW 1
+ #define _PAGE_BIT_USER 2
+ #define _PAGE_BIT_PWT 3
+ #define _PAGE_BIT_PCD 4
+ #define _PAGE_BIT_ACCESSED 5
+ #define _PAGE_BIT_DIRTY 6
+ #define _PAGE_BIT_PSE 7 /* 4 MB (or 2MB) page, Pentium+, if present.. */
+ #define _PAGE_BIT_GLOBAL 8 /* Global TLB entry PPro+ */
+
+ #define _PAGE_PRESENT 0x001
+ #define _PAGE_RW 0x002
+ #define _PAGE_USER 0x004
+ #define _PAGE_PWT 0x008
+ #define _PAGE_PCD 0x010
+ #define _PAGE_ACCESSED 0x020
+ #define _PAGE_DIRTY 0x040
+ #define _PAGE_PSE 0x080 /* 4 MB (or 2MB) page, Pentium+, if present.. */
+ #define _PAGE_GLOBAL 0x100 /* Global TLB entry PPro+ */
+
+ #define _PAGE_PROTNONE 0x080 /* If not present */
+
+ #define _PAGE_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED | _PAGE_DIRTY)
+ #define _KERNPG_TABLE (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | _PAGE_DIRTY)
+ #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
+
+ #define PAGE_NONE __pgprot(_PAGE_PROTNONE | _PAGE_ACCESSED)
+ #define PAGE_SHARED __pgprot(_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED)
+ #define PAGE_COPY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+ #define PAGE_READONLY __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
+
+ #define __PAGE_KERNEL \
+ (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+ #define __PAGE_KERNEL_NOCACHE \
+ (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED)
+ #define __PAGE_KERNEL_RO \
+ (_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED)
+
+ #if 0
+ #define MAKE_GLOBAL(x) __pgprot((x) | _PAGE_GLOBAL)
+ #else
+ #define MAKE_GLOBAL(x) __pgprot(x)
+ #endif
+
+ #define PAGE_KERNEL MAKE_GLOBAL(__PAGE_KERNEL)
+ #define PAGE_KERNEL_RO MAKE_GLOBAL(__PAGE_KERNEL_RO)
+ #define PAGE_KERNEL_NOCACHE MAKE_GLOBAL(__PAGE_KERNEL_NOCACHE)
+
+ /*
+ * The i386 can't do page protection for execute, and considers that
+ * the same are read. Also, write permissions imply read permissions.
+ * This is the closest we can get..
+ */
+ #define __P000 PAGE_NONE
+ #define __P001 PAGE_READONLY
+ #define __P010 PAGE_COPY
+ #define __P011 PAGE_COPY
+ #define __P100 PAGE_READONLY
+ #define __P101 PAGE_READONLY
+ #define __P110 PAGE_COPY
+ #define __P111 PAGE_COPY
+
+ #define __S000 PAGE_NONE
+ #define __S001 PAGE_READONLY
+ #define __S010 PAGE_SHARED
+ #define __S011 PAGE_SHARED
+ #define __S100 PAGE_READONLY
+ #define __S101 PAGE_READONLY
+ #define __S110 PAGE_SHARED
+ #define __S111 PAGE_SHARED
+
+ #define pte_present(x) ((x).pte_low & (_PAGE_PRESENT | _PAGE_PROTNONE))
-#define pmd_none(x) (!(x).pmd)
-#define pmd_present(x) ((x).pmd & _PAGE_PRESENT)
++#define pte_clear(xp) do { set_pte(xp, __pte(0)); } while (0)
+
-#define pmd_bad(x) (((x).pmd & (~PAGE_MASK & ~_PAGE_USER)) != _KERNPG_TABLE)
++#define pmd_none(x) (!pmd_val(x))
++/* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
++ can temporarily clear it. */
++#define pmd_present(x) (pmd_val(x))
+ #define pmd_clear(xp) do { set_pmd(xp, __pmd(0)); } while (0)
- unsigned long pteval = *(unsigned long *)ptep;
- int ret = pteval & _PAGE_DIRTY;
- if ( ret ) queue_l1_entry_update(ptep, pteval & ~_PAGE_DIRTY);
- return ret;
++#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
+
+
+ #define pages_to_mb(x) ((x) >> (20-PAGE_SHIFT))
+
+ /*
+ * The following only work if pte_present() is true.
+ * Undefined behaviour if not..
+ */
+ static inline int pte_read(pte_t pte) { return (pte).pte_low & _PAGE_USER; }
+ static inline int pte_exec(pte_t pte) { return (pte).pte_low & _PAGE_USER; }
+ static inline int pte_dirty(pte_t pte) { return (pte).pte_low & _PAGE_DIRTY; }
+ static inline int pte_young(pte_t pte) { return (pte).pte_low & _PAGE_ACCESSED; }
+ static inline int pte_write(pte_t pte) { return (pte).pte_low & _PAGE_RW; }
+
+ static inline pte_t pte_rdprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; }
+ static inline pte_t pte_exprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_USER; return pte; }
+ static inline pte_t pte_mkclean(pte_t pte) { (pte).pte_low &= ~_PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkold(pte_t pte) { (pte).pte_low &= ~_PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_wrprotect(pte_t pte) { (pte).pte_low &= ~_PAGE_RW; return pte; }
+ static inline pte_t pte_mkread(pte_t pte) { (pte).pte_low |= _PAGE_USER; return pte; }
+ static inline pte_t pte_mkexec(pte_t pte) { (pte).pte_low |= _PAGE_USER; return pte; }
+ static inline pte_t pte_mkdirty(pte_t pte) { (pte).pte_low |= _PAGE_DIRTY; return pte; }
+ static inline pte_t pte_mkyoung(pte_t pte) { (pte).pte_low |= _PAGE_ACCESSED; return pte; }
+ static inline pte_t pte_mkwrite(pte_t pte) { (pte).pte_low |= _PAGE_RW; return pte; }
+
+ static inline int ptep_test_and_clear_dirty(pte_t *ptep)
+ {
-static inline int ptep_test_and_clear_young(pte_t *ptep)
++ if (!pte_dirty(*ptep))
++ return 0;
++ return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
+ }
- unsigned long pteval = *(unsigned long *)ptep;
- int ret = pteval & _PAGE_ACCESSED;
- if ( ret ) queue_l1_entry_update(ptep, pteval & ~_PAGE_ACCESSED);
- return ret;
++
++static inline int ptep_test_and_clear_young(pte_t *ptep)
+ {
- unsigned long pteval = *(unsigned long *)ptep;
- if ( (pteval & _PAGE_RW) )
- queue_l1_entry_update(ptep, pteval & ~_PAGE_RW);
++ if (!pte_young(*ptep))
++ return 0;
++ return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
+ }
++
+ static inline void ptep_set_wrprotect(pte_t *ptep)
+ {
- unsigned long pteval = *(unsigned long *)ptep;
- if ( !(pteval & _PAGE_DIRTY) )
- queue_l1_entry_update(ptep, pteval | _PAGE_DIRTY);
++ if (pte_write(*ptep))
++ clear_bit(_PAGE_BIT_RW, &ptep->pte_low);
+ }
++
+ static inline void ptep_mkdirty(pte_t *ptep)
+ {
- queue_l1_entry_update(pte, (*(unsigned long *)pte)&~_PAGE_RW);
++ if (!pte_dirty(*ptep))
++ set_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
+ }
+
+ /*
+ * Conversion functions: convert a page and protection to a page entry,
+ * and a page entry and page directory to the page they refer to.
+ */
+
+ #define mk_pte(page, pgprot) __mk_pte((page) - mem_map, (pgprot))
+
+ /* This takes a physical page address that is used by the remapping functions */
+ #define mk_pte_phys(physpage, pgprot) __mk_pte((physpage) >> PAGE_SHIFT, pgprot)
+
+ static inline pte_t pte_modify(pte_t pte, pgprot_t newprot)
+ {
+ pte.pte_low &= _PAGE_CHG_MASK;
+ pte.pte_low |= pgprot_val(newprot);
+ return pte;
+ }
+
+ #define page_pte(page) page_pte_prot(page, __pgprot(0))
+
+ #define pmd_page(pmd) \
+ ((unsigned long) __va(pmd_val(pmd) & PAGE_MASK))
+
+ /* to find an entry in a page-table-directory. */
+ #define pgd_index(address) ((address >> PGDIR_SHIFT) & (PTRS_PER_PGD-1))
+
+ #define __pgd_offset(address) pgd_index(address)
+
+ #define pgd_offset(mm, address) ((mm)->pgd+pgd_index(address))
+
+ /* to find an entry in a kernel page-table-directory */
+ #define pgd_offset_k(address) pgd_offset(&init_mm, address)
+
+ #define __pmd_offset(address) \
+ (((address) >> PMD_SHIFT) & (PTRS_PER_PMD-1))
+
+ /* Find an entry in the third-level page table.. */
+ #define __pte_offset(address) \
+ ((address >> PAGE_SHIFT) & (PTRS_PER_PTE - 1))
+ #define pte_offset(dir, address) ((pte_t *) pmd_page(*(dir)) + \
+ __pte_offset(address))
+
+ /*
+ * The i386 doesn't have any external MMU info: the kernel page
+ * tables contain all the necessary information.
+ */
+ #define update_mmu_cache(vma,address,pte) do { } while (0)
+
+ /* Encode and de-code a swap entry */
+ #define SWP_TYPE(x) (((x).val >> 1) & 0x3f)
+ #define SWP_OFFSET(x) ((x).val >> 8)
+ #define SWP_ENTRY(type, offset) ((swp_entry_t) { ((type) << 1) | ((offset) << 8) })
+ #define pte_to_swp_entry(pte) ((swp_entry_t) { (pte).pte_low })
+ #define swp_entry_to_pte(x) ((pte_t) { (x).val })
+
+ struct page;
+ int change_page_attr(struct page *, int, pgprot_t prot);
+
+ static inline void __make_page_readonly(void *va)
+ {
+ pgd_t *pgd = pgd_offset_k((unsigned long)va);
+ pmd_t *pmd = pmd_offset(pgd, (unsigned long)va);
+ pte_t *pte = pte_offset(pmd, (unsigned long)va);
- queue_l1_entry_update(pte, (*(unsigned long *)pte)|_PAGE_RW);
++ set_pte(pte, pte_wrprotect(*pte));
+ }
+
+ static inline void __make_page_writable(void *va)
+ {
+ pgd_t *pgd = pgd_offset_k((unsigned long)va);
+ pmd_t *pmd = pmd_offset(pgd, (unsigned long)va);
+ pte_t *pte = pte_offset(pmd, (unsigned long)va);
- queue_l1_entry_update(pte, (*(unsigned long *)pte)&~_PAGE_RW);
++ set_pte(pte, pte_mkwrite(*pte));
+ }
+
+ static inline void make_page_readonly(void *va)
+ {
+ pgd_t *pgd = pgd_offset_k((unsigned long)va);
+ pmd_t *pmd = pmd_offset(pgd, (unsigned long)va);
+ pte_t *pte = pte_offset(pmd, (unsigned long)va);
- queue_l1_entry_update(pte, (*(unsigned long *)pte)|_PAGE_RW);
++ set_pte(pte, pte_wrprotect(*pte));
+ if ( (unsigned long)va >= VMALLOC_START )
+ __make_page_readonly(machine_to_virt(
+ *(unsigned long *)pte&PAGE_MASK));
+ }
+
+ static inline void make_page_writable(void *va)
+ {
+ pgd_t *pgd = pgd_offset_k((unsigned long)va);
+ pmd_t *pmd = pmd_offset(pgd, (unsigned long)va);
+ pte_t *pte = pte_offset(pmd, (unsigned long)va);
++ set_pte(pte, pte_mkwrite(*pte));
+ if ( (unsigned long)va >= VMALLOC_START )
+ __make_page_writable(machine_to_virt(
+ *(unsigned long *)pte&PAGE_MASK));
+ }
+
+ static inline void make_pages_readonly(void *va, unsigned int nr)
+ {
+ while ( nr-- != 0 )
+ {
+ make_page_readonly(va);
+ va = (void *)((unsigned long)va + PAGE_SIZE);
+ }
+ }
+
+ static inline void make_pages_writable(void *va, unsigned int nr)
+ {
+ while ( nr-- != 0 )
+ {
+ make_page_writable(va);
+ va = (void *)((unsigned long)va + PAGE_SIZE);
+ }
+ }
+
+ static inline unsigned long arbitrary_virt_to_machine(void *va)
+ {
+ pgd_t *pgd = pgd_offset_k((unsigned long)va);
+ pmd_t *pmd = pmd_offset(pgd, (unsigned long)va);
+ pte_t *pte = pte_offset(pmd, (unsigned long)va);
+ unsigned long pa = (*(unsigned long *)pte) & PAGE_MASK;
+ return pa | ((unsigned long)va & (PAGE_SIZE-1));
+ }
+
+ #endif /* !__ASSEMBLY__ */
+
+ /* Needs to be defined here and not in linux/mm.h, as it is arch dependent */
+ #define PageSkip(page) (0)
+ #define kern_addr_valid(addr) (1)
+
+ #define io_remap_page_range remap_page_range
+
+ #endif /* _I386_PGTABLE_H */
--- /dev/null
-#define stts() (HYPERVISOR_fpu_taskswitch())
+ #ifndef __ASM_SYSTEM_H
+ #define __ASM_SYSTEM_H
+
+ #include <linux/config.h>
+ #include <linux/kernel.h>
+ #include <linux/init.h>
+ #include <linux/bitops.h>
+ #include <asm/synch_bitops.h>
+ #include <asm/segment.h>
+ #include <asm/hypervisor.h>
+ #include <asm/evtchn.h>
+
+ #ifdef __KERNEL__
+
+ struct task_struct;
+ extern void FASTCALL(__switch_to(struct task_struct *prev,
+ struct task_struct *next));
+
+ #define prepare_to_switch() \
+ do { \
+ struct thread_struct *__t = ¤t->thread; \
+ __asm__ __volatile__ ( "movl %%fs,%0" : "=m" (*(int *)&__t->fs) ); \
+ __asm__ __volatile__ ( "movl %%gs,%0" : "=m" (*(int *)&__t->gs) ); \
+ } while (0)
+ #define switch_to(prev,next,last) do { \
+ asm volatile("pushl %%esi\n\t" \
+ "pushl %%edi\n\t" \
+ "pushl %%ebp\n\t" \
+ "movl %%esp,%0\n\t" /* save ESP */ \
+ "movl %3,%%esp\n\t" /* restore ESP */ \
+ "movl $1f,%1\n\t" /* save EIP */ \
+ "pushl %4\n\t" /* restore EIP */ \
+ "jmp __switch_to\n" \
+ "1:\t" \
+ "popl %%ebp\n\t" \
+ "popl %%edi\n\t" \
+ "popl %%esi\n\t" \
+ :"=m" (prev->thread.esp),"=m" (prev->thread.eip), \
+ "=b" (last) \
+ :"m" (next->thread.esp),"m" (next->thread.eip), \
+ "a" (prev), "d" (next), \
+ "b" (prev)); \
+ } while (0)
+
+ #define _set_base(addr,base) do { unsigned long __pr; \
+ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
+ "rorl $16,%%edx\n\t" \
+ "movb %%dl,%2\n\t" \
+ "movb %%dh,%3" \
+ :"=&d" (__pr) \
+ :"m" (*((addr)+2)), \
+ "m" (*((addr)+4)), \
+ "m" (*((addr)+7)), \
+ "0" (base) \
+ ); } while(0)
+
+ #define _set_limit(addr,limit) do { unsigned long __lr; \
+ __asm__ __volatile__ ("movw %%dx,%1\n\t" \
+ "rorl $16,%%edx\n\t" \
+ "movb %2,%%dh\n\t" \
+ "andb $0xf0,%%dh\n\t" \
+ "orb %%dh,%%dl\n\t" \
+ "movb %%dl,%2" \
+ :"=&d" (__lr) \
+ :"m" (*(addr)), \
+ "m" (*((addr)+6)), \
+ "0" (limit) \
+ ); } while(0)
+
+ #define set_base(ldt,base) _set_base( ((char *)&(ldt)) , (base) )
+ #define set_limit(ldt,limit) _set_limit( ((char *)&(ldt)) , ((limit)-1)>>12 )
+
+ static inline unsigned long _get_base(char * addr)
+ {
+ unsigned long __base;
+ __asm__("movb %3,%%dh\n\t"
+ "movb %2,%%dl\n\t"
+ "shll $16,%%edx\n\t"
+ "movw %1,%%dx"
+ :"=&d" (__base)
+ :"m" (*((addr)+2)),
+ "m" (*((addr)+4)),
+ "m" (*((addr)+7)));
+ return __base;
+ }
+
+ #define get_base(ldt) _get_base( ((char *)&(ldt)) )
+
+ /*
+ * Load a segment. Fall back on loading the zero
+ * segment if something goes wrong..
+ */
+ #define loadsegment(seg,value) \
+ asm volatile("\n" \
+ "1:\t" \
+ "movl %0,%%" #seg "\n" \
+ "2:\n" \
+ ".section .fixup,\"ax\"\n" \
+ "3:\t" \
+ "pushl $0\n\t" \
+ "popl %%" #seg "\n\t" \
+ "jmp 2b\n" \
+ ".previous\n" \
+ ".section __ex_table,\"a\"\n\t" \
+ ".align 4\n\t" \
+ ".long 1b,3b\n" \
+ ".previous" \
+ : :"m" (*(unsigned int *)&(value)))
+
+ /* NB. 'clts' is done for us by Xen during virtual trap. */
+ #define clts() ((void)0)
++#define stts() (HYPERVISOR_fpu_taskswitch(1))
+
+ #endif /* __KERNEL__ */
+
+ /**
+ * __ffs - find first bit in word.
+ * @word: The word to search
+ *
+ * Undefined if no bit exists, so code should check against 0 first.
+ *
+ * Taken from 2.6 for Xen.
+ */
+ static inline unsigned long __ffs(unsigned long word)
+ {
+ __asm__("bsfl %1,%0"
+ :"=r" (word)
+ :"rm" (word));
+ return word;
+ }
+
+ static inline unsigned long get_limit(unsigned long segment)
+ {
+ unsigned long __limit;
+ __asm__("lsll %1,%0"
+ :"=r" (__limit):"r" (segment));
+ return __limit+1;
+ }
+
+ #define nop() __asm__ __volatile__ ("nop")
+
+ #define xchg(ptr,v) ((__typeof__(*(ptr)))__xchg((unsigned long)(v),(ptr),sizeof(*(ptr))))
+
+ #define tas(ptr) (xchg((ptr),1))
+
+ struct __xchg_dummy { unsigned long a[100]; };
+ #define __xg(x) ((struct __xchg_dummy *)(x))
+
+
+ /*
+ * The semantics of XCHGCMP8B are a bit strange, this is why
+ * there is a loop and the loading of %%eax and %%edx has to
+ * be inside. This inlines well in most cases, the cached
+ * cost is around ~38 cycles. (in the future we might want
+ * to do an SIMD/3DNOW!/MMX/FPU 64-bit store here, but that
+ * might have an implicit FPU-save as a cost, so it's not
+ * clear which path to go.)
+ *
+ * chmxchg8b must be used with the lock prefix here to allow
+ * the instruction to be executed atomically, see page 3-102
+ * of the instruction set reference 24319102.pdf. We need
+ * the reader side to see the coherent 64bit value.
+ */
+ static inline void __set_64bit (unsigned long long * ptr,
+ unsigned int low, unsigned int high)
+ {
+ __asm__ __volatile__ (
+ "\n1:\t"
+ "movl (%0), %%eax\n\t"
+ "movl 4(%0), %%edx\n\t"
+ "lock cmpxchg8b (%0)\n\t"
+ "jnz 1b"
+ : /* no outputs */
+ : "D"(ptr),
+ "b"(low),
+ "c"(high)
+ : "ax","dx","memory");
+ }
+
+ static inline void __set_64bit_constant (unsigned long long *ptr,
+ unsigned long long value)
+ {
+ __set_64bit(ptr,(unsigned int)(value), (unsigned int)((value)>>32ULL));
+ }
+ #define ll_low(x) *(((unsigned int*)&(x))+0)
+ #define ll_high(x) *(((unsigned int*)&(x))+1)
+
+ static inline void __set_64bit_var (unsigned long long *ptr,
+ unsigned long long value)
+ {
+ __set_64bit(ptr,ll_low(value), ll_high(value));
+ }
+
+ #define set_64bit(ptr,value) \
+ (__builtin_constant_p(value) ? \
+ __set_64bit_constant(ptr, value) : \
+ __set_64bit_var(ptr, value) )
+
+ #define _set_64bit(ptr,value) \
+ (__builtin_constant_p(value) ? \
+ __set_64bit(ptr, (unsigned int)(value), (unsigned int)((value)>>32ULL) ) : \
+ __set_64bit(ptr, ll_low(value), ll_high(value)) )
+
+ /*
+ * Note: no "lock" prefix even on SMP: xchg always implies lock anyway
+ * Note 2: xchg has side effect, so that attribute volatile is necessary,
+ * but generally the primitive is invalid, *ptr is output argument. --ANK
+ */
+ static inline unsigned long __xchg(unsigned long x, volatile void * ptr, int size)
+ {
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("xchgb %b0,%1"
+ :"=q" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 2:
+ __asm__ __volatile__("xchgw %w0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ case 4:
+ __asm__ __volatile__("xchgl %0,%1"
+ :"=r" (x)
+ :"m" (*__xg(ptr)), "0" (x)
+ :"memory");
+ break;
+ }
+ return x;
+ }
+
+ /*
+ * Atomic compare and exchange. Compare OLD with MEM, if identical,
+ * store NEW in MEM. Return the initial value in MEM. Success is
+ * indicated by comparing RETURN with OLD.
+ */
+
+ #ifdef CONFIG_X86_CMPXCHG
+ #define __HAVE_ARCH_CMPXCHG 1
+
+ static inline unsigned long __cmpxchg(volatile void *ptr, unsigned long old,
+ unsigned long new, int size)
+ {
+ unsigned long prev;
+ switch (size) {
+ case 1:
+ __asm__ __volatile__("lock cmpxchgb %b1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ case 2:
+ __asm__ __volatile__("lock cmpxchgw %w1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ case 4:
+ __asm__ __volatile__("lock cmpxchgl %1,%2"
+ : "=a"(prev)
+ : "q"(new), "m"(*__xg(ptr)), "0"(old)
+ : "memory");
+ return prev;
+ }
+ return old;
+ }
+
+ #define cmpxchg(ptr,o,n)\
+ ((__typeof__(*(ptr)))__cmpxchg((ptr),(unsigned long)(o),\
+ (unsigned long)(n),sizeof(*(ptr))))
+
+ #else
+ /* Compiling for a 386 proper. Is it worth implementing via cli/sti? */
+ #endif
+
+ /*
+ * Force strict CPU ordering.
+ * And yes, this is required on UP too when we're talking
+ * to devices.
+ *
+ * For now, "wmb()" doesn't actually do anything, as all
+ * Intel CPU's follow what Intel calls a *Processor Order*,
+ * in which all writes are seen in the program order even
+ * outside the CPU.
+ *
+ * I expect future Intel CPU's to have a weaker ordering,
+ * but I'd also expect them to finally get their act together
+ * and add some real memory barriers if so.
+ *
+ * Some non intel clones support out of order store. wmb() ceases to be a
+ * nop for these.
+ */
+
+ #define mb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+ #define rmb() mb()
+
+ #ifdef CONFIG_X86_OOSTORE
+ #define wmb() __asm__ __volatile__ ("lock; addl $0,0(%%esp)": : :"memory")
+ #else
+ #define wmb() __asm__ __volatile__ ("": : :"memory")
+ #endif
+
+ #ifdef CONFIG_SMP
+ #define smp_mb() mb()
+ #define smp_rmb() rmb()
+ #define smp_wmb() wmb()
+ #define set_mb(var, value) do { xchg(&var, value); } while (0)
+ #else
+ #define smp_mb() barrier()
+ #define smp_rmb() barrier()
+ #define smp_wmb() barrier()
+ #define set_mb(var, value) do { var = value; barrier(); } while (0)
+ #endif
+
+ #define set_wmb(var, value) do { var = value; wmb(); } while (0)
+
+ #define safe_halt() ((void)0)
+
+ /*
+ * The use of 'barrier' in the following reflects their use as local-lock
+ * operations. Reentrancy must be prevented (e.g., __cli()) /before/ following
+ * critical operations are executed. All critical operatiosn must complete
+ * /before/ reentrancy is permitted (e.g., __sti()). Alpha architecture also
+ * includes these barriers, for example.
+ */
+
+ #define __cli() \
+ do { \
+ HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask = 1; \
+ barrier(); \
+ } while (0)
+
+ #define __sti() \
+ do { \
+ shared_info_t *_shared = HYPERVISOR_shared_info; \
+ barrier(); \
+ _shared->vcpu_data[0].evtchn_upcall_mask = 0; \
+ barrier(); /* unmask then check (avoid races) */ \
+ if ( unlikely(_shared->vcpu_data[0].evtchn_upcall_pending) ) \
+ force_evtchn_callback(); \
+ } while (0)
+
+ #define __save_flags(x) \
+ do { \
+ (x) = HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask; \
+ } while (0)
+
+ #define __restore_flags(x) \
+ do { \
+ shared_info_t *_shared = HYPERVISOR_shared_info; \
+ barrier(); \
+ if ( (_shared->vcpu_data[0].evtchn_upcall_mask = x) == 0 ) { \
+ barrier(); /* unmask then check (avoid races) */ \
+ if ( unlikely(_shared->vcpu_data[0].evtchn_upcall_pending) ) \
+ force_evtchn_callback(); \
+ } \
+ } while (0)
+
+ #define __save_and_cli(x) \
+ do { \
+ (x) = HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask; \
+ HYPERVISOR_shared_info->vcpu_data[0].evtchn_upcall_mask = 1; \
+ barrier(); \
+ } while (0)
+
+ #define __save_and_sti(x) \
+ do { \
+ shared_info_t *_shared = HYPERVISOR_shared_info; \
+ barrier(); \
+ (x) = _shared->vcpu_data[0].evtchn_upcall_mask; \
+ _shared->vcpu_data[0].evtchn_upcall_mask = 0; \
+ barrier(); /* unmask then check (avoid races) */ \
+ if ( unlikely(_shared->vcpu_data[0].evtchn_upcall_pending) ) \
+ force_evtchn_callback(); \
+ } while (0)
+
+ #define local_irq_save(x) __save_and_cli(x)
+ #define local_irq_set(x) __save_and_sti(x)
+ #define local_irq_restore(x) __restore_flags(x)
+ #define local_irq_disable() __cli()
+ #define local_irq_enable() __sti()
+
+
+ #ifdef CONFIG_SMP
+ #error no SMP
+ extern void __global_cli(void);
+ extern void __global_sti(void);
+ extern unsigned long __global_save_flags(void);
+ extern void __global_restore_flags(unsigned long);
+ #define cli() __global_cli()
+ #define sti() __global_sti()
+ #define save_flags(x) ((x)=__global_save_flags())
+ #define restore_flags(x) __global_restore_flags(x)
+ #define save_and_cli(x) do { save_flags(x); cli(); } while(0);
+ #define save_and_sti(x) do { save_flags(x); sti(); } while(0);
+
+ #else
+
+ #define cli() __cli()
+ #define sti() __sti()
+ #define save_flags(x) __save_flags(x)
+ #define restore_flags(x) __restore_flags(x)
+ #define save_and_cli(x) __save_and_cli(x)
+ #define save_and_sti(x) __save_and_sti(x)
+
+ #endif
+
+ /*
+ * disable hlt during certain critical i/o operations
+ */
+ #define HAVE_DISABLE_HLT
+ void disable_hlt(void);
+ void enable_hlt(void);
+
+ extern unsigned long dmi_broken;
+ extern int is_sony_vaio_laptop;
+
+ #define BROKEN_ACPI_Sx 0x0001
+ #define BROKEN_INIT_AFTER_S1 0x0002
+ #define BROKEN_PNP_BIOS 0x0004
+
+ #endif
--- /dev/null
-ln -sf ../../${LINUX_26}/include/asm-xen/multicall.h
+ #!/bin/bash
+
+ # mkbuildtree <build tree>
+ #
+ # Creates symbolic links in <build tree> for the sparse tree
+ # in the current directory.
+
+ # Script to determine the relative path between two directories.
+ # Copyright (c) D. J. Hawkey Jr. 2002
+ # Fixed for Xen project by K. Fraser in 2003.
+ abs_to_rel ()
+ {
+ local CWD SRCPATH
+
+ if [ "$1" != "/" -a "${1##*[^/]}" = "/" ]; then
+ SRCPATH=${1%?}
+ else
+ SRCPATH=$1
+ fi
+ if [ "$2" != "/" -a "${2##*[^/]}" = "/" ]; then
+ DESTPATH=${2%?}
+ else
+ DESTPATH=$2
+ fi
+
+ CWD=$PWD
+ [ "${1%%[^/]*}" != "/" ] && cd $1 && SRCPATH=$PWD
+ [ "${2%%[^/]*}" != "/" ] && cd $2 && DESTPATH=$PWD
+ [ "$CWD" != "$PWD" ] && cd $CWD
+
+ BASEPATH=$SRCPATH
+
+ [ "$SRCPATH" = "$DESTPATH" ] && DESTPATH="." && return
+ [ "$SRCPATH" = "/" ] && DESTPATH=${DESTPATH#?} && return
+
+ while [ "$BASEPATH/" != "${DESTPATH%${DESTPATH#$BASEPATH/}}" ]; do
+ BASEPATH=${BASEPATH%/*}
+ done
+
+ SRCPATH=${SRCPATH#$BASEPATH}
+ DESTPATH=${DESTPATH#$BASEPATH}
+ DESTPATH=${DESTPATH#?}
+ while [ -n "$SRCPATH" ]; do
+ SRCPATH=${SRCPATH%/*}
+ DESTPATH="../$DESTPATH"
+ done
+
+ [ -z "$BASEPATH" ] && BASEPATH="/"
+ [ "${DESTPATH##*[^/]}" = "/" ] && DESTPATH=${DESTPATH%?}
+ }
+
+ # relative_lndir <target_dir>
+ # Creates a tree of symlinks in the current working directory that mirror
+ # real files in <target_dir>. <target_dir> should be relative to the current
+ # working directory. Symlinks in <target_dir> are ignored. Source-control files
+ # are ignored.
+ relative_lndir ()
+ {
+ local SYMLINK_DIR REAL_DIR pref i j
+ SYMLINK_DIR=$PWD
+ REAL_DIR=$1
+ (
+ cd $REAL_DIR
+ for i in `find . -type d | grep -v SCCS`; do
+ [ -d $SYMLINK_DIR/$i ] || mkdir -p $SYMLINK_DIR/$i
+ (
+ cd $i
+ pref=`echo $i | sed -e 's#/[^/]*#../#g' -e 's#^\.##'`
+ for j in `find . -maxdepth 1 -type f -o -type l`; do
+ ln -sf ${pref}${REAL_DIR}/$i/$j ${SYMLINK_DIR}/$i/$j
+ done
+ )
+ done
+ )
+ }
+
+ [ "$1" == "" ] && { echo "Syntax: $0 <linux tree to xenify>"; exit 1; }
+
+ # Get absolute path to the destination directory
+ pushd . >/dev/null
+ cd ${1} || { echo "cannot cd to ${1}"; exit 1; }
+ AD=$PWD
+ popd >/dev/null
+
+ # Get absolute path to the source directory
+ AS=`pwd`
+
+ # Get path to source, relative to destination
+ abs_to_rel ${AD} ${AS}
+ RS=$DESTPATH
+
+ # Remove old copies of files and directories at the destination
+ for i in `find . -type f -o -type l` ; do rm -f ${AD}/${i#./} ; done
+
+ # We now work from the destination directory
+ cd ${AD} || { echo "cannot cd to ${AD}"; exit 1; }
+
+ # Remove old symlinks
+ for i in `find . -type l`; do rm -f $i; done
+
+ # Create symlinks of files and directories which exist in the sparse source
+ relative_lndir ${RS}
+ rm -f mkbuildtree
+
+ set ${RS}/../linux-2.6.*-xen-sparse
+ [ "$1" == "${RS}/../linux-2.6.*-xen-parse" ] && { echo "no Linux 2.6 sparse tree at ${RS}/../linux-2.6.*-xen-sparse"; exit 1; }
+ LINUX_26="$1"
+
+
+ # Create links to the shared definitions of the Xen interfaces.
+ rm -rf ${AD}/include/asm-xen/xen-public
+ mkdir ${AD}/include/asm-xen/xen-public
+ cd ${AD}/include/asm-xen/xen-public
+ relative_lndir ../../../${RS}/../xen/include/public
+
+ # Create a link to the shared definitions for the control interface
+ cd ${AD}/include/asm-xen
+
+ ## Symlinks for files:
+ ## - which are identical in the i386 and xen-i386 architecture-dependent
+ ## subdirectories.
+ ## - which are identical in the Linux 2.6 and Linux 2.4 ports.
+
+ cd ${AD}/include/asm-xen
+ ln -sf ../asm-i386/a.out.h
+ ln -sf ../asm-i386/apicdef.h
+ ln -sf ../asm-i386/apic.h
+ ln -sf ../asm-i386/atomic.h
+ ln -sf ../asm-i386/bitops.h
+ ln -sf ../asm-i386/boot.h
+ ln -sf ../asm-i386/byteorder.h
+ ln -sf ../asm-i386/cache.h
+ ln -sf ../asm-i386/checksum.h
+ ln -sf ../asm-i386/cpufeature.h
+ ln -sf ../asm-i386/current.h
+ ln -sf ../asm-i386/debugreg.h
+ ln -sf ../asm-i386/delay.h
+ ln -sf ../asm-i386/div64.h
+ ln -sf ../asm-i386/dma.h
+ ln -sf ../asm-i386/elf.h
+ ln -sf ../asm-i386/errno.h
+ ln -sf ../asm-i386/fcntl.h
+ ln -sf ../asm-i386/floppy.h
+ ln -sf ../asm-i386/hardirq.h
+ ln -sf ../asm-i386/hdreg.h
+ ln -sf ../asm-i386/i387.h
+ ln -sf ../asm-i386/ide.h
+ ln -sf ../asm-i386/init.h
+ ln -sf ../asm-i386/io_apic.h
+ ln -sf ../asm-i386/ioctl.h
+ ln -sf ../asm-i386/ioctls.h
+ ln -sf ../asm-i386/ipcbuf.h
+ ln -sf ../asm-i386/ipc.h
+ ln -sf ../asm-i386/kmap_types.h
+ ln -sf ../asm-i386/ldt.h
+ ln -sf ../asm-i386/linux_logo.h
+ ln -sf ../asm-i386/locks.h
+ ln -sf ../asm-i386/math_emu.h
+ ln -sf ../asm-i386/mc146818rtc.h
+ ln -sf ../asm-i386/mca_dma.h
+ ln -sf ../asm-i386/mman.h
+ ln -sf ../asm-i386/mmu.h
+ ln -sf ../asm-i386/mmx.h
+ ln -sf ../asm-i386/mpspec.h
+ ln -sf ../asm-i386/msgbuf.h
++ln -sf ../asm-i386/msr.h
+ ln -sf ../asm-i386/mtrr.h
+ ln -sf ../asm-i386/namei.h
+ ln -sf ../asm-i386/param.h
+ ln -sf ../asm-i386/parport.h
+ ln -sf ../asm-i386/pgtable-3level.h
+ ln -sf ../asm-i386/poll.h
+ ln -sf ../asm-i386/posix_types.h
+ ln -sf ../asm-i386/ptrace.h
+ ln -sf ../asm-i386/resource.h
+ ln -sf ../asm-i386/rwlock.h
+ ln -sf ../asm-i386/rwsem.h
+ ln -sf ../asm-i386/scatterlist.h
+ ln -sf ../asm-i386/semaphore.h
+ ln -sf ../asm-i386/sembuf.h
+ ln -sf ../asm-i386/serial.h
+ ln -sf ../asm-i386/setup.h
+ ln -sf ../asm-i386/shmbuf.h
+ ln -sf ../asm-i386/shmparam.h
+ ln -sf ../asm-i386/sigcontext.h
+ ln -sf ../asm-i386/siginfo.h
+ ln -sf ../asm-i386/signal.h
+ ln -sf ../asm-i386/smplock.h
+ ln -sf ../asm-i386/socket.h
+ ln -sf ../asm-i386/sockios.h
+ ln -sf ../asm-i386/softirq.h
+ ln -sf ../asm-i386/spinlock.h
+ ln -sf ../asm-i386/statfs.h
+ ln -sf ../asm-i386/stat.h
+ ln -sf ../asm-i386/string-486.h
+ ln -sf ../asm-i386/string.h
+ ln -sf ../asm-i386/termbits.h
+ ln -sf ../asm-i386/termios.h
+ ln -sf ../asm-i386/timex.h
+ ln -sf ../asm-i386/tlb.h
+ ln -sf ../asm-i386/types.h
+ ln -sf ../asm-i386/uaccess.h
+ ln -sf ../asm-i386/ucontext.h
+ ln -sf ../asm-i386/unaligned.h
+ ln -sf ../asm-i386/unistd.h
+ ln -sf ../asm-i386/user.h
+ ln -sf ../asm-i386/vm86.h
+ ln -sf ../../${LINUX_26}/include/asm-xen/balloon.h
+ ln -sf ../../${LINUX_26}/include/asm-xen/ctrl_if.h
+ ln -sf ../../${LINUX_26}/include/asm-xen/evtchn.h
++ln -sf ../../${LINUX_26}/include/asm-xen/gnttab.h
+ ln -sf ../../${LINUX_26}/include/asm-xen/hypervisor.h
-ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/ioport.c
-ln -sf ../../../${LINUX_26}/arch/xen/i386/kernel/pci-dma.c
+ ln -sf ../../${LINUX_26}/include/asm-xen/xen_proc.h
+ ln -sf ../../${LINUX_26}/include/asm-xen/asm-i386/synch_bitops.h
++ln -sf ../../${LINUX_26}/include/asm-xen/asm-i386/hypercall.h
+
+ mkdir -p linux-public && cd linux-public
+ ln -sf ../../../${LINUX_26}/include/asm-xen/linux-public/privcmd.h
+ ln -sf ../../../${LINUX_26}/include/asm-xen/linux-public/suspend.h
+
+ cd ${AD}/arch/xen/kernel
+ ln -sf ../../i386/kernel/i387.c
+ ln -sf ../../i386/kernel/init_task.c
+ ln -sf ../../i386/kernel/pci-i386.c
+ ln -sf ../../i386/kernel/pci-i386.h
+ ln -sf ../../i386/kernel/ptrace.c
+ ln -sf ../../i386/kernel/semaphore.c
+ ln -sf ../../i386/kernel/sys_i386.c
+ ln -sf ../../../${LINUX_26}/arch/xen/kernel/ctrl_if.c
+ ln -sf ../../../${LINUX_26}/arch/xen/kernel/evtchn.c
+ ln -sf ../../../${LINUX_26}/arch/xen/kernel/fixup.c
++ln -sf ../../../${LINUX_26}/arch/xen/kernel/gnttab.c
+ ln -sf ../../../${LINUX_26}/arch/xen/kernel/reboot.c
+ ln -sf ../../../${LINUX_26}/arch/xen/kernel/skbuff.c
+
+ cd ${AD}/arch/xen/lib
+ ln -sf ../../i386/lib/checksum.S
+ ln -sf ../../i386/lib/dec_and_lock.c
+ ln -sf ../../i386/lib/getuser.S
+ ln -sf ../../i386/lib/iodebug.c
+ ln -sf ../../i386/lib/memcpy.c
+ ln -sf ../../i386/lib/mmx.c
+ ln -sf ../../i386/lib/old-checksum.c
+ ln -sf ../../i386/lib/strstr.c
+ ln -sf ../../i386/lib/usercopy.c
+ ln -sf ../../../${LINUX_26}/arch/xen/kernel/xen_proc.c
+
+ cd ${AD}/arch/xen/mm
+ ln -sf ../../i386/mm/extable.c
+ ln -sf ../../i386/mm/pageattr.c
+ ln -sf ../../../${LINUX_26}/arch/xen/i386/mm/hypervisor.c
+
+ cd ${AD}/arch/xen/drivers/balloon
+ ln -sf ../../../../${LINUX_26}/drivers/xen/balloon/balloon.c
+
+ cd ${AD}/arch/xen/drivers/console
+ ln -sf ../../../../${LINUX_26}/drivers/xen/console/console.c
+
+ cd ${AD}/arch/xen/drivers/dom0
+ ln -sf ../../../../${LINUX_26}/drivers/xen/privcmd/privcmd.c core.c
+
+ cd ${AD}/arch/xen/drivers/evtchn
+ ln -sf ../../../../${LINUX_26}/drivers/xen/evtchn/evtchn.c
+
+ cd ${AD}/arch/xen/drivers/netif/frontend
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/netfront/netfront.c main.c
+
+ cd ${AD}/arch/xen/drivers/netif/backend
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/common.h
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/control.c
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/interface.c
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/netback/netback.c main.c
+
+ cd ${AD}/arch/xen/drivers/blkif/backend
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/blkback/common.h
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/blkback/blkback.c main.c
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/blkback/control.c
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/blkback/interface.c
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/blkback/vbd.c
+
+ cd ${AD}/arch/xen/drivers/blkif/frontend
+ ln -sf ../../../../../${LINUX_26}/drivers/xen/blkfront/blkfront.c
+
++cd ${AD}/arch/xen/drivers/usbif/frontend
++ln -sf ../../../../../${LINUX_26}/drivers/xen/usbfront/usbfront.c main.c
++ln -sf ../../../../../${LINUX_26}/drivers/xen/usbfront/xhci.h
+
++cd ${AD}/arch/xen/drivers/usbif/backend
++ln -sf ../../../../../${LINUX_26}/drivers/xen/usbback/common.h
++ln -sf ../../../../../${LINUX_26}/drivers/xen/usbback/control.c
++ln -sf ../../../../../${LINUX_26}/drivers/xen/usbback/interface.c
++ln -sf ../../../../../${LINUX_26}/drivers/xen/usbback/usbback.c main.c
--- /dev/null
- XEN_flush_page_update_queue();
+ /*
+ * High memory handling common code and variables.
+ *
+ * (C) 1999 Andrea Arcangeli, SuSE GmbH, andrea@suse.de
+ * Gerhard Wichert, Siemens AG, Gerhard.Wichert@pdb.siemens.de
+ *
+ *
+ * Redesigned the x86 32-bit VM architecture to deal with
+ * 64-bit physical space. With current x86 CPUs this
+ * means up to 64 Gigabytes physical RAM.
+ *
+ * Rewrote high memory support to move the page cache into
+ * high memory. Implemented permanent (schedulable) kmaps
+ * based on Linus' idea.
+ *
+ * Copyright (C) 1999 Ingo Molnar <mingo@redhat.com>
+ */
+
+ #include <linux/mm.h>
+ #include <linux/pagemap.h>
+ #include <linux/highmem.h>
+ #include <linux/swap.h>
+ #include <linux/slab.h>
+
+ /*
+ * Virtual_count is not a pure "count".
+ * 0 means that it is not mapped, and has not been mapped
+ * since a TLB flush - it is usable.
+ * 1 means that there are no users, but it has been mapped
+ * since the last TLB flush - so we can't use it.
+ * n means that there are (n-1) current users of it.
+ */
+ static int pkmap_count[LAST_PKMAP];
+ static unsigned int last_pkmap_nr;
+ static spinlock_cacheline_t kmap_lock_cacheline = {SPIN_LOCK_UNLOCKED};
+ #define kmap_lock kmap_lock_cacheline.lock
+
+ pte_t * pkmap_page_table;
+
+ static DECLARE_WAIT_QUEUE_HEAD(pkmap_map_wait);
+
+ static void flush_all_zero_pkmaps(void)
+ {
+ int i;
+
+ flush_cache_all();
+
+ for (i = 0; i < LAST_PKMAP; i++) {
+ struct page *page;
+
+ /*
+ * zero means we don't have anything to do,
+ * >1 means that it is still in use. Only
+ * a count of 1 means that it is free but
+ * needs to be unmapped
+ */
+ if (pkmap_count[i] != 1)
+ continue;
+ pkmap_count[i] = 0;
+
+ /* sanity check */
+ if (pte_none(pkmap_page_table[i]))
+ BUG();
+
+ /*
+ * Don't need an atomic fetch-and-clear op here;
+ * no-one has the page mapped, and cannot get at
+ * its virtual address (and hence PTE) without first
+ * getting the kmap_lock (which is held here).
+ * So no dangers, even with speculative execution.
+ */
+ page = pte_page(pkmap_page_table[i]);
+ pte_clear(&pkmap_page_table[i]);
+
+ page->virtual = NULL;
+ }
+ flush_tlb_all();
+ }
+
+ static inline unsigned long map_new_virtual(struct page *page, int nonblocking)
+ {
+ unsigned long vaddr;
+ int count;
+
+ start:
+ count = LAST_PKMAP;
+ /* Find an empty entry */
+ for (;;) {
+ last_pkmap_nr = (last_pkmap_nr + 1) & LAST_PKMAP_MASK;
+ if (!last_pkmap_nr) {
+ flush_all_zero_pkmaps();
+ count = LAST_PKMAP;
+ }
+ if (!pkmap_count[last_pkmap_nr])
+ break; /* Found a usable entry */
+ if (--count)
+ continue;
+
+ if (nonblocking)
+ return 0;
+
+ /*
+ * Sleep for somebody else to unmap their entries
+ */
+ {
+ DECLARE_WAITQUEUE(wait, current);
+
+ current->state = TASK_UNINTERRUPTIBLE;
+ add_wait_queue(&pkmap_map_wait, &wait);
+ spin_unlock(&kmap_lock);
+ schedule();
+ remove_wait_queue(&pkmap_map_wait, &wait);
+ spin_lock(&kmap_lock);
+
+ /* Somebody else might have mapped it while we slept */
+ if (page->virtual)
+ return (unsigned long) page->virtual;
+
+ /* Re-start */
+ goto start;
+ }
+ }
+ vaddr = PKMAP_ADDR(last_pkmap_nr);
+ set_pte(&(pkmap_page_table[last_pkmap_nr]), mk_pte(page, kmap_prot));
+
+ pkmap_count[last_pkmap_nr] = 1;
+ page->virtual = (void *) vaddr;
+
+ return vaddr;
+ }
+
+ void kmap_flush_unused(void)
+ {
+ spin_lock(&kmap_lock);
+ flush_all_zero_pkmaps();
+ spin_unlock(&kmap_lock);
+ }
+
+ void fastcall *kmap_high(struct page *page, int nonblocking)
+ {
+ unsigned long vaddr;
+
+ /*
+ * For highmem pages, we can't trust "virtual" until
+ * after we have the lock.
+ *
+ * We cannot call this from interrupts, as it may block
+ */
+ spin_lock(&kmap_lock);
+ vaddr = (unsigned long) page->virtual;
+ if (!vaddr) {
+ vaddr = map_new_virtual(page, nonblocking);
+ if (!vaddr)
+ goto out;
+ }
+ pkmap_count[PKMAP_NR(vaddr)]++;
+ if (pkmap_count[PKMAP_NR(vaddr)] < 2)
+ BUG();
+ out:
+ spin_unlock(&kmap_lock);
+ return (void*) vaddr;
+ }
+
+ void fastcall kunmap_high(struct page *page)
+ {
+ unsigned long vaddr;
+ unsigned long nr;
+ int need_wakeup;
+
+ spin_lock(&kmap_lock);
+ vaddr = (unsigned long) page->virtual;
+ if (!vaddr)
+ BUG();
+ nr = PKMAP_NR(vaddr);
+
+ /*
+ * A count must never go down to zero
+ * without a TLB flush!
+ */
+ need_wakeup = 0;
+ switch (--pkmap_count[nr]) {
+ case 0:
+ BUG();
+ case 1:
+ /*
+ * Avoid an unnecessary wake_up() function call.
+ * The common case is pkmap_count[] == 1, but
+ * no waiters.
+ * The tasks queued in the wait-queue are guarded
+ * by both the lock in the wait-queue-head and by
+ * the kmap_lock. As the kmap_lock is held here,
+ * no need for the wait-queue-head's lock. Simply
+ * test if the queue is empty.
+ */
+ need_wakeup = waitqueue_active(&pkmap_map_wait);
+ }
+ spin_unlock(&kmap_lock);
+
+ /* do wake-up, if needed, race-free outside of the spin lock */
+ if (need_wakeup)
+ wake_up(&pkmap_map_wait);
+ }
+
+ #define POOL_SIZE 32
+
+ /*
+ * This lock gets no contention at all, normally.
+ */
+ static spinlock_t emergency_lock = SPIN_LOCK_UNLOCKED;
+
+ int nr_emergency_pages;
+ static LIST_HEAD(emergency_pages);
+
+ int nr_emergency_bhs;
+ static LIST_HEAD(emergency_bhs);
+
+ /*
+ * Simple bounce buffer support for highmem pages.
+ * This will be moved to the block layer in 2.5.
+ */
+
+ static inline void copy_from_high_bh (struct buffer_head *to,
+ struct buffer_head *from)
+ {
+ struct page *p_from;
+ char *vfrom;
+
+ p_from = from->b_page;
+
+ vfrom = kmap_atomic(p_from, KM_USER0);
+ memcpy(to->b_data, vfrom + bh_offset(from), to->b_size);
+ kunmap_atomic(vfrom, KM_USER0);
+ }
+
+ static inline void copy_to_high_bh_irq (struct buffer_head *to,
+ struct buffer_head *from)
+ {
+ struct page *p_to;
+ char *vto;
+ unsigned long flags;
+
+ p_to = to->b_page;
+ __save_flags(flags);
+ __cli();
+ vto = kmap_atomic(p_to, KM_BOUNCE_READ);
+ memcpy(vto + bh_offset(to), from->b_data, to->b_size);
+ kunmap_atomic(vto, KM_BOUNCE_READ);
+ __restore_flags(flags);
+ }
+
+ static inline void bounce_end_io (struct buffer_head *bh, int uptodate)
+ {
+ struct page *page;
+ struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_private);
+ unsigned long flags;
+
+ bh_orig->b_end_io(bh_orig, uptodate);
+
+ page = bh->b_page;
+
+ spin_lock_irqsave(&emergency_lock, flags);
+ if (nr_emergency_pages >= POOL_SIZE)
+ __free_page(page);
+ else {
+ /*
+ * We are abusing page->list to manage
+ * the highmem emergency pool:
+ */
+ list_add(&page->list, &emergency_pages);
+ nr_emergency_pages++;
+ }
+
+ if (nr_emergency_bhs >= POOL_SIZE) {
+ #ifdef HIGHMEM_DEBUG
+ /* Don't clobber the constructed slab cache */
+ init_waitqueue_head(&bh->b_wait);
+ #endif
+ kmem_cache_free(bh_cachep, bh);
+ } else {
+ /*
+ * Ditto in the bh case, here we abuse b_inode_buffers:
+ */
+ list_add(&bh->b_inode_buffers, &emergency_bhs);
+ nr_emergency_bhs++;
+ }
+ spin_unlock_irqrestore(&emergency_lock, flags);
+ }
+
+ static __init int init_emergency_pool(void)
+ {
+ struct sysinfo i;
+ si_meminfo(&i);
+ si_swapinfo(&i);
+
+ if (!i.totalhigh)
+ return 0;
+
+ spin_lock_irq(&emergency_lock);
+ while (nr_emergency_pages < POOL_SIZE) {
+ struct page * page = alloc_page(GFP_ATOMIC);
+ if (!page) {
+ printk("couldn't refill highmem emergency pages");
+ break;
+ }
+ list_add(&page->list, &emergency_pages);
+ nr_emergency_pages++;
+ }
+ while (nr_emergency_bhs < POOL_SIZE) {
+ struct buffer_head * bh = kmem_cache_alloc(bh_cachep, SLAB_ATOMIC);
+ if (!bh) {
+ printk("couldn't refill highmem emergency bhs");
+ break;
+ }
+ list_add(&bh->b_inode_buffers, &emergency_bhs);
+ nr_emergency_bhs++;
+ }
+ spin_unlock_irq(&emergency_lock);
+ printk("allocated %d pages and %d bhs reserved for the highmem bounces\n",
+ nr_emergency_pages, nr_emergency_bhs);
+
+ return 0;
+ }
+
+ __initcall(init_emergency_pool);
+
+ static void bounce_end_io_write (struct buffer_head *bh, int uptodate)
+ {
+ bounce_end_io(bh, uptodate);
+ }
+
+ static void bounce_end_io_read (struct buffer_head *bh, int uptodate)
+ {
+ struct buffer_head *bh_orig = (struct buffer_head *)(bh->b_private);
+
+ if (uptodate)
+ copy_to_high_bh_irq(bh_orig, bh);
+ bounce_end_io(bh, uptodate);
+ }
+
+ struct page *alloc_bounce_page (void)
+ {
+ struct list_head *tmp;
+ struct page *page;
+
+ page = alloc_page(GFP_NOHIGHIO);
+ if (page)
+ return page;
+ /*
+ * No luck. First, kick the VM so it doesn't idle around while
+ * we are using up our emergency rations.
+ */
+ wakeup_bdflush();
+
+ repeat_alloc:
+ /*
+ * Try to allocate from the emergency pool.
+ */
+ tmp = &emergency_pages;
+ spin_lock_irq(&emergency_lock);
+ if (!list_empty(tmp)) {
+ page = list_entry(tmp->next, struct page, list);
+ list_del(tmp->next);
+ nr_emergency_pages--;
+ }
+ spin_unlock_irq(&emergency_lock);
+ if (page)
+ return page;
+
+ /* we need to wait I/O completion */
+ run_task_queue(&tq_disk);
+
+ yield();
+ goto repeat_alloc;
+ }
+
+ struct buffer_head *alloc_bounce_bh (void)
+ {
+ struct list_head *tmp;
+ struct buffer_head *bh;
+
+ bh = kmem_cache_alloc(bh_cachep, SLAB_NOHIGHIO);
+ if (bh)
+ return bh;
+ /*
+ * No luck. First, kick the VM so it doesn't idle around while
+ * we are using up our emergency rations.
+ */
+ wakeup_bdflush();
+
+ repeat_alloc:
+ /*
+ * Try to allocate from the emergency pool.
+ */
+ tmp = &emergency_bhs;
+ spin_lock_irq(&emergency_lock);
+ if (!list_empty(tmp)) {
+ bh = list_entry(tmp->next, struct buffer_head, b_inode_buffers);
+ list_del(tmp->next);
+ nr_emergency_bhs--;
+ }
+ spin_unlock_irq(&emergency_lock);
+ if (bh)
+ return bh;
+
+ /* we need to wait I/O completion */
+ run_task_queue(&tq_disk);
+
+ yield();
+ goto repeat_alloc;
+ }
+
+ struct buffer_head * create_bounce(int rw, struct buffer_head * bh_orig)
+ {
+ struct page *page;
+ struct buffer_head *bh;
+
+ if (!PageHighMem(bh_orig->b_page))
+ return bh_orig;
+
+ bh = alloc_bounce_bh();
+ /*
+ * This is wasteful for 1k buffers, but this is a stopgap measure
+ * and we are being ineffective anyway. This approach simplifies
+ * things immensly. On boxes with more than 4GB RAM this should
+ * not be an issue anyway.
+ */
+ page = alloc_bounce_page();
+
+ set_bh_page(bh, page, 0);
+
+ bh->b_next = NULL;
+ bh->b_blocknr = bh_orig->b_blocknr;
+ bh->b_size = bh_orig->b_size;
+ bh->b_list = -1;
+ bh->b_dev = bh_orig->b_dev;
+ bh->b_count = bh_orig->b_count;
+ bh->b_rdev = bh_orig->b_rdev;
+ bh->b_state = bh_orig->b_state;
+ #ifdef HIGHMEM_DEBUG
+ bh->b_flushtime = jiffies;
+ bh->b_next_free = NULL;
+ bh->b_prev_free = NULL;
+ /* bh->b_this_page */
+ bh->b_reqnext = NULL;
+ bh->b_pprev = NULL;
+ #endif
+ /* bh->b_page */
+ if (rw == WRITE) {
+ bh->b_end_io = bounce_end_io_write;
+ copy_from_high_bh(bh, bh_orig);
+ } else
+ bh->b_end_io = bounce_end_io_read;
+ bh->b_private = (void *)bh_orig;
+ bh->b_rsector = bh_orig->b_rsector;
+ #ifdef HIGHMEM_DEBUG
+ memset(&bh->b_wait, -1, sizeof(bh->b_wait));
+ #endif
+
+ return bh;
+ }
+
--- /dev/null
- XEN_flush_page_update_queue();
+ /*
+ * linux/mm/memory.c
+ *
+ * Copyright (C) 1991, 1992, 1993, 1994 Linus Torvalds
+ */
+
+ /*
+ * demand-loading started 01.12.91 - seems it is high on the list of
+ * things wanted, and it should be easy to implement. - Linus
+ */
+
+ /*
+ * Ok, demand-loading was easy, shared pages a little bit tricker. Shared
+ * pages started 02.12.91, seems to work. - Linus.
+ *
+ * Tested sharing by executing about 30 /bin/sh: under the old kernel it
+ * would have taken more than the 6M I have free, but it worked well as
+ * far as I could see.
+ *
+ * Also corrected some "invalidate()"s - I wasn't doing enough of them.
+ */
+
+ /*
+ * Real VM (paging to/from disk) started 18.12.91. Much more work and
+ * thought has to go into this. Oh, well..
+ * 19.12.91 - works, somewhat. Sometimes I get faults, don't know why.
+ * Found it. Everything seems to work now.
+ * 20.12.91 - Ok, making the swap-device changeable like the root.
+ */
+
+ /*
+ * 05.04.94 - Multi-page memory management added for v1.1.
+ * Idea by Alex Bligh (alex@cconcepts.co.uk)
+ *
+ * 16.07.99 - Support of BIGMEM added by Gerhard Wichert, Siemens AG
+ * (Gerhard.Wichert@pdb.siemens.de)
+ */
+
+ #include <linux/mm.h>
+ #include <linux/mman.h>
+ #include <linux/swap.h>
+ #include <linux/smp_lock.h>
+ #include <linux/swapctl.h>
+ #include <linux/iobuf.h>
+ #include <linux/highmem.h>
+ #include <linux/pagemap.h>
+ #include <linux/module.h>
+
+ #include <asm/pgalloc.h>
+ #include <asm/uaccess.h>
+ #include <asm/tlb.h>
+
+ unsigned long max_mapnr;
+ unsigned long num_physpages;
+ unsigned long num_mappedpages;
+ void * high_memory;
+ struct page *highmem_start_page;
+
+ /*
+ * We special-case the C-O-W ZERO_PAGE, because it's such
+ * a common occurrence (no need to read the page to know
+ * that it's zero - better for the cache and memory subsystem).
+ */
+ static inline void copy_cow_page(struct page * from, struct page * to, unsigned long address)
+ {
+ if (from == ZERO_PAGE(address)) {
+ clear_user_highpage(to, address);
+ return;
+ }
+ copy_user_highpage(to, from, address);
+ }
+
+ mem_map_t * mem_map;
+
+ /*
+ * Called by TLB shootdown
+ */
+ void __free_pte(pte_t pte)
+ {
+ struct page *page = pte_page(pte);
+ if ((!VALID_PAGE(page)) || PageReserved(page))
+ return;
+ if (pte_dirty(pte))
+ set_page_dirty(page);
+ free_page_and_swap_cache(page);
+ }
+
+
+ /*
+ * Note: this doesn't free the actual pages themselves. That
+ * has been handled earlier when unmapping all the memory regions.
+ */
+ static inline void free_one_pmd(pmd_t * dir)
+ {
+ pte_t * pte;
+
+ if (pmd_none(*dir))
+ return;
+ if (pmd_bad(*dir)) {
+ pmd_ERROR(*dir);
+ pmd_clear(dir);
+ return;
+ }
+ pte = pte_offset(dir, 0);
+ pmd_clear(dir);
+ pte_free(pte);
+ }
+
+ static inline void free_one_pgd(pgd_t * dir)
+ {
+ int j;
+ pmd_t * pmd;
+
+ if (pgd_none(*dir))
+ return;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return;
+ }
+ pmd = pmd_offset(dir, 0);
+ pgd_clear(dir);
+ for (j = 0; j < PTRS_PER_PMD ; j++) {
+ prefetchw(pmd+j+(PREFETCH_STRIDE/16));
+ free_one_pmd(pmd+j);
+ }
+ pmd_free(pmd);
+ }
+
+ /* Low and high watermarks for page table cache.
+ The system should try to have pgt_water[0] <= cache elements <= pgt_water[1]
+ */
+ int pgt_cache_water[2] = { 25, 50 };
+
+ /* Returns the number of pages freed */
+ int check_pgt_cache(void)
+ {
+ return do_check_pgt_cache(pgt_cache_water[0], pgt_cache_water[1]);
+ }
+
+
+ /*
+ * This function clears all user-level page tables of a process - this
+ * is needed by execve(), so that old pages aren't in the way.
+ */
+ void clear_page_tables(struct mm_struct *mm, unsigned long first, int nr)
+ {
+ pgd_t * page_dir = mm->pgd;
+
+ spin_lock(&mm->page_table_lock);
+ page_dir += first;
+ do {
+ free_one_pgd(page_dir);
+ page_dir++;
+ } while (--nr);
- /* XEN modification: modified ordering here to avoid RaW hazard. */
- pte = *src_pte;
- pte = pte_wrprotect(pte);
+ spin_unlock(&mm->page_table_lock);
+
+ /* keep the page table cache within bounds */
+ check_pgt_cache();
+ }
+
+ #define PTE_TABLE_MASK ((PTRS_PER_PTE-1) * sizeof(pte_t))
+ #define PMD_TABLE_MASK ((PTRS_PER_PMD-1) * sizeof(pmd_t))
+
+ /*
+ * copy one vm_area from one task to the other. Assumes the page tables
+ * already present in the new task to be cleared in the whole range
+ * covered by this vma.
+ *
+ * 08Jan98 Merged into one routine from several inline routines to reduce
+ * variable count and make things faster. -jj
+ *
+ * dst->page_table_lock is held on entry and exit,
+ * but may be dropped within pmd_alloc() and pte_alloc().
+ */
+ int copy_page_range(struct mm_struct *dst, struct mm_struct *src,
+ struct vm_area_struct *vma)
+ {
+ pgd_t * src_pgd, * dst_pgd;
+ unsigned long address = vma->vm_start;
+ unsigned long end = vma->vm_end;
+ unsigned long cow = (vma->vm_flags & (VM_SHARED | VM_MAYWRITE)) == VM_MAYWRITE;
+
+ src_pgd = pgd_offset(src, address)-1;
+ dst_pgd = pgd_offset(dst, address)-1;
+
+ for (;;) {
+ pmd_t * src_pmd, * dst_pmd;
+
+ src_pgd++; dst_pgd++;
+
+ /* copy_pmd_range */
+
+ if (pgd_none(*src_pgd))
+ goto skip_copy_pmd_range;
+ if (pgd_bad(*src_pgd)) {
+ pgd_ERROR(*src_pgd);
+ pgd_clear(src_pgd);
+ skip_copy_pmd_range: address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ if (!address || (address >= end))
+ goto out;
+ continue;
+ }
+
+ src_pmd = pmd_offset(src_pgd, address);
+ dst_pmd = pmd_alloc(dst, dst_pgd, address);
+ if (!dst_pmd)
+ goto nomem;
+
+ do {
+ pte_t * src_pte, * dst_pte;
+
+ /* copy_pte_range */
+
+ if (pmd_none(*src_pmd))
+ goto skip_copy_pte_range;
+ if (pmd_bad(*src_pmd)) {
+ pmd_ERROR(*src_pmd);
+ pmd_clear(src_pmd);
+ skip_copy_pte_range: address = (address + PMD_SIZE) & PMD_MASK;
+ if (address >= end)
+ goto out;
+ goto cont_copy_pmd_range;
+ }
+
+ src_pte = pte_offset(src_pmd, address);
+ dst_pte = pte_alloc(dst, dst_pmd, address);
+ if (!dst_pte)
+ goto nomem;
+
+ spin_lock(&src->page_table_lock);
+ do {
+ pte_t pte = *src_pte;
+ struct page *ptepage;
+
+ /* copy_one_pte */
+
+ if (pte_none(pte))
+ goto cont_copy_pte_range_noset;
+ if (!pte_present(pte)) {
+ swap_duplicate(pte_to_swp_entry(pte));
+ goto cont_copy_pte_range;
+ }
+ ptepage = pte_page(pte);
+ if ((!VALID_PAGE(ptepage)) ||
+ PageReserved(ptepage))
+ goto cont_copy_pte_range;
+
+ /* If it's a COW mapping, write protect it both in the parent and the child */
+ if (cow && pte_write(pte)) {
- XEN_flush_page_update_queue();
- HYPERVISOR_update_va_mapping(address>>PAGE_SHIFT, entry, UVMF_INVLPG);
+ ptep_set_wrprotect(src_pte);
++ pte = *src_pte;
+ }
+
+ /* If it's a shared mapping, mark it clean in the child */
+ if (vma->vm_flags & VM_SHARED)
+ pte = pte_mkclean(pte);
+ pte = pte_mkold(pte);
+ get_page(ptepage);
+ dst->rss++;
+
+ cont_copy_pte_range: set_pte(dst_pte, pte);
+ cont_copy_pte_range_noset: address += PAGE_SIZE;
+ if (address >= end)
+ goto out_unlock;
+ src_pte++;
+ dst_pte++;
+ } while ((unsigned long)src_pte & PTE_TABLE_MASK);
+ spin_unlock(&src->page_table_lock);
+
+ cont_copy_pmd_range: src_pmd++;
+ dst_pmd++;
+ } while ((unsigned long)src_pmd & PMD_TABLE_MASK);
+ }
+ out_unlock:
+ spin_unlock(&src->page_table_lock);
+ out:
+ return 0;
+ nomem:
+ return -ENOMEM;
+ }
+
+ /*
+ * Return indicates whether a page was freed so caller can adjust rss
+ */
+ static inline void forget_pte(pte_t page)
+ {
+ if (!pte_none(page)) {
+ printk("forget_pte: old mapping existed!\n");
+ BUG();
+ }
+ }
+
+ static inline int zap_pte_range(mmu_gather_t *tlb, pmd_t * pmd, unsigned long address, unsigned long size)
+ {
+ unsigned long offset;
+ pte_t * ptep;
+ int freed = 0;
+
+ if (pmd_none(*pmd))
+ return 0;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ return 0;
+ }
+ ptep = pte_offset(pmd, address);
+ offset = address & ~PMD_MASK;
+ if (offset + size > PMD_SIZE)
+ size = PMD_SIZE - offset;
+ size &= PAGE_MASK;
+ for (offset=0; offset < size; ptep++, offset += PAGE_SIZE) {
+ pte_t pte = *ptep;
+ if (pte_none(pte))
+ continue;
+ if (pte_present(pte)) {
+ struct page *page = pte_page(pte);
+ if (VALID_PAGE(page) && !PageReserved(page))
+ freed ++;
+ /* This will eventually call __free_pte on the pte. */
+ tlb_remove_page(tlb, ptep, address + offset);
+ } else {
+ free_swap_and_cache(pte_to_swp_entry(pte));
+ pte_clear(ptep);
+ }
+ }
+
+ return freed;
+ }
+
+ static inline int zap_pmd_range(mmu_gather_t *tlb, pgd_t * dir, unsigned long address, unsigned long size)
+ {
+ pmd_t * pmd;
+ unsigned long end;
+ int freed;
+
+ if (pgd_none(*dir))
+ return 0;
+ if (pgd_bad(*dir)) {
+ pgd_ERROR(*dir);
+ pgd_clear(dir);
+ return 0;
+ }
+ pmd = pmd_offset(dir, address);
+ end = address + size;
+ if (end > ((address + PGDIR_SIZE) & PGDIR_MASK))
+ end = ((address + PGDIR_SIZE) & PGDIR_MASK);
+ freed = 0;
+ do {
+ freed += zap_pte_range(tlb, pmd, address, end - address);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address < end);
+ return freed;
+ }
+
+ /*
+ * remove user pages in a given range.
+ */
+ void zap_page_range(struct mm_struct *mm, unsigned long address, unsigned long size)
+ {
+ mmu_gather_t *tlb;
+ pgd_t * dir;
+ unsigned long start = address, end = address + size;
+ int freed = 0;
+
+ dir = pgd_offset(mm, address);
+
+ /*
+ * This is a long-lived spinlock. That's fine.
+ * There's no contention, because the page table
+ * lock only protects against kswapd anyway, and
+ * even if kswapd happened to be looking at this
+ * process we _want_ it to get stuck.
+ */
+ if (address >= end)
+ BUG();
+ spin_lock(&mm->page_table_lock);
+ flush_cache_range(mm, address, end);
+ tlb = tlb_gather_mmu(mm);
+
+ do {
+ freed += zap_pmd_range(tlb, dir, address, end - address);
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+
+ /* this will flush any remaining tlb entries */
+ tlb_finish_mmu(tlb, start, end);
+
+ /*
+ * Update rss for the mm_struct (not necessarily current->mm)
+ * Notice that rss is an unsigned long.
+ */
+ if (mm->rss > freed)
+ mm->rss -= freed;
+ else
+ mm->rss = 0;
+ spin_unlock(&mm->page_table_lock);
+ }
+
+ /*
+ * Do a quick page-table lookup for a single page.
+ */
+ static struct page * follow_page(struct mm_struct *mm, unsigned long address, int write)
+ {
+ pgd_t *pgd;
+ pmd_t *pmd;
+ pte_t *ptep, pte;
+
+ pgd = pgd_offset(mm, address);
+ if (pgd_none(*pgd) || pgd_bad(*pgd))
+ goto out;
+
+ pmd = pmd_offset(pgd, address);
+ if (pmd_none(*pmd) || pmd_bad(*pmd))
+ goto out;
+
+ ptep = pte_offset(pmd, address);
+ if (!ptep)
+ goto out;
+
+ pte = *ptep;
+ if (pte_present(pte)) {
+ if (!write ||
+ (pte_write(pte) && pte_dirty(pte)))
+ return pte_page(pte);
+ }
+
+ out:
+ return 0;
+ }
+
+ /*
+ * Given a physical address, is there a useful struct page pointing to
+ * it? This may become more complex in the future if we start dealing
+ * with IO-aperture pages in kiobufs.
+ */
+
+ static inline struct page * get_page_map(struct page *page)
+ {
+ if (!VALID_PAGE(page))
+ return 0;
+ return page;
+ }
+
+ /*
+ * Please read Documentation/cachetlb.txt before using this function,
+ * accessing foreign memory spaces can cause cache coherency problems.
+ *
+ * Accessing a VM_IO area is even more dangerous, therefore the function
+ * fails if pages is != NULL and a VM_IO area is found.
+ */
+ int get_user_pages(struct task_struct *tsk, struct mm_struct *mm, unsigned long start,
+ int len, int write, int force, struct page **pages, struct vm_area_struct **vmas)
+ {
+ int i;
+ unsigned int flags;
+
+ /*
+ * Require read or write permissions.
+ * If 'force' is set, we only require the "MAY" flags.
+ */
+ flags = write ? (VM_WRITE | VM_MAYWRITE) : (VM_READ | VM_MAYREAD);
+ flags &= force ? (VM_MAYREAD | VM_MAYWRITE) : (VM_READ | VM_WRITE);
+ i = 0;
+
+ do {
+ struct vm_area_struct * vma;
+
+ vma = find_extend_vma(mm, start);
+
+ if ( !vma || (pages && vma->vm_flags & VM_IO) || !(flags & vma->vm_flags) )
+ return i ? : -EFAULT;
+
+ spin_lock(&mm->page_table_lock);
+ do {
+ struct page *map;
+ while (!(map = follow_page(mm, start, write))) {
+ spin_unlock(&mm->page_table_lock);
+ switch (handle_mm_fault(mm, vma, start, write)) {
+ case 1:
+ tsk->min_flt++;
+ break;
+ case 2:
+ tsk->maj_flt++;
+ break;
+ case 0:
+ if (i) return i;
+ return -EFAULT;
+ default:
+ if (i) return i;
+ return -ENOMEM;
+ }
+ spin_lock(&mm->page_table_lock);
+ }
+ if (pages) {
+ pages[i] = get_page_map(map);
+ /* FIXME: call the correct function,
+ * depending on the type of the found page
+ */
+ if (!pages[i] || PageReserved(pages[i])) {
+ if (pages[i] != ZERO_PAGE(start))
+ goto bad_page;
+ } else
+ page_cache_get(pages[i]);
+ }
+ if (vmas)
+ vmas[i] = vma;
+ i++;
+ start += PAGE_SIZE;
+ len--;
+ } while(len && start < vma->vm_end);
+ spin_unlock(&mm->page_table_lock);
+ } while(len);
+ out:
+ return i;
+
+ /*
+ * We found an invalid page in the VMA. Release all we have
+ * so far and fail.
+ */
+ bad_page:
+ spin_unlock(&mm->page_table_lock);
+ while (i--)
+ page_cache_release(pages[i]);
+ i = -EFAULT;
+ goto out;
+ }
+
+ EXPORT_SYMBOL(get_user_pages);
+
+ /*
+ * Force in an entire range of pages from the current process's user VA,
+ * and pin them in physical memory.
+ */
+ #define dprintk(x...)
+
+ int map_user_kiobuf(int rw, struct kiobuf *iobuf, unsigned long va, size_t len)
+ {
+ int pgcount, err;
+ struct mm_struct * mm;
+
+ /* Make sure the iobuf is not already mapped somewhere. */
+ if (iobuf->nr_pages)
+ return -EINVAL;
+
+ mm = current->mm;
+ dprintk ("map_user_kiobuf: begin\n");
+
+ pgcount = (va + len + PAGE_SIZE - 1)/PAGE_SIZE - va/PAGE_SIZE;
+ /* mapping 0 bytes is not permitted */
+ if (!pgcount) BUG();
+ err = expand_kiobuf(iobuf, pgcount);
+ if (err)
+ return err;
+
+ iobuf->locked = 0;
+ iobuf->offset = va & (PAGE_SIZE-1);
+ iobuf->length = len;
+
+ /* Try to fault in all of the necessary pages */
+ down_read(&mm->mmap_sem);
+ /* rw==READ means read from disk, write into memory area */
+ err = get_user_pages(current, mm, va, pgcount,
+ (rw==READ), 0, iobuf->maplist, NULL);
+ up_read(&mm->mmap_sem);
+ if (err < 0) {
+ unmap_kiobuf(iobuf);
+ dprintk ("map_user_kiobuf: end %d\n", err);
+ return err;
+ }
+ iobuf->nr_pages = err;
+ while (pgcount--) {
+ /* FIXME: flush superflous for rw==READ,
+ * probably wrong function for rw==WRITE
+ */
+ flush_dcache_page(iobuf->maplist[pgcount]);
+ }
+ dprintk ("map_user_kiobuf: end OK\n");
+ return 0;
+ }
+
+ /*
+ * Mark all of the pages in a kiobuf as dirty
+ *
+ * We need to be able to deal with short reads from disk: if an IO error
+ * occurs, the number of bytes read into memory may be less than the
+ * size of the kiobuf, so we have to stop marking pages dirty once the
+ * requested byte count has been reached.
+ *
+ * Must be called from process context - set_page_dirty() takes VFS locks.
+ */
+
+ void mark_dirty_kiobuf(struct kiobuf *iobuf, int bytes)
+ {
+ int index, offset, remaining;
+ struct page *page;
+
+ index = iobuf->offset >> PAGE_SHIFT;
+ offset = iobuf->offset & ~PAGE_MASK;
+ remaining = bytes;
+ if (remaining > iobuf->length)
+ remaining = iobuf->length;
+
+ while (remaining > 0 && index < iobuf->nr_pages) {
+ page = iobuf->maplist[index];
+
+ if (!PageReserved(page))
+ set_page_dirty(page);
+
+ remaining -= (PAGE_SIZE - offset);
+ offset = 0;
+ index++;
+ }
+ }
+
+ /*
+ * Unmap all of the pages referenced by a kiobuf. We release the pages,
+ * and unlock them if they were locked.
+ */
+
+ void unmap_kiobuf (struct kiobuf *iobuf)
+ {
+ int i;
+ struct page *map;
+
+ for (i = 0; i < iobuf->nr_pages; i++) {
+ map = iobuf->maplist[i];
+ if (map) {
+ if (iobuf->locked)
+ UnlockPage(map);
+ /* FIXME: cache flush missing for rw==READ
+ * FIXME: call the correct reference counting function
+ */
+ page_cache_release(map);
+ }
+ }
+
+ iobuf->nr_pages = 0;
+ iobuf->locked = 0;
+ }
+
+
+ /*
+ * Lock down all of the pages of a kiovec for IO.
+ *
+ * If any page is mapped twice in the kiovec, we return the error -EINVAL.
+ *
+ * The optional wait parameter causes the lock call to block until all
+ * pages can be locked if set. If wait==0, the lock operation is
+ * aborted if any locked pages are found and -EAGAIN is returned.
+ */
+
+ int lock_kiovec(int nr, struct kiobuf *iovec[], int wait)
+ {
+ struct kiobuf *iobuf;
+ int i, j;
+ struct page *page, **ppage;
+ int doublepage = 0;
+ int repeat = 0;
+
+ repeat:
+
+ for (i = 0; i < nr; i++) {
+ iobuf = iovec[i];
+
+ if (iobuf->locked)
+ continue;
+
+ ppage = iobuf->maplist;
+ for (j = 0; j < iobuf->nr_pages; ppage++, j++) {
+ page = *ppage;
+ if (!page)
+ continue;
+
+ if (TryLockPage(page)) {
+ while (j--) {
+ struct page *tmp = *--ppage;
+ if (tmp)
+ UnlockPage(tmp);
+ }
+ goto retry;
+ }
+ }
+ iobuf->locked = 1;
+ }
+
+ return 0;
+
+ retry:
+
+ /*
+ * We couldn't lock one of the pages. Undo the locking so far,
+ * wait on the page we got to, and try again.
+ */
+
+ unlock_kiovec(nr, iovec);
+ if (!wait)
+ return -EAGAIN;
+
+ /*
+ * Did the release also unlock the page we got stuck on?
+ */
+ if (!PageLocked(page)) {
+ /*
+ * If so, we may well have the page mapped twice
+ * in the IO address range. Bad news. Of
+ * course, it _might_ just be a coincidence,
+ * but if it happens more than once, chances
+ * are we have a double-mapped page.
+ */
+ if (++doublepage >= 3)
+ return -EINVAL;
+
+ /* Try again... */
+ wait_on_page(page);
+ }
+
+ if (++repeat < 16)
+ goto repeat;
+ return -EAGAIN;
+ }
+
+ /*
+ * Unlock all of the pages of a kiovec after IO.
+ */
+
+ int unlock_kiovec(int nr, struct kiobuf *iovec[])
+ {
+ struct kiobuf *iobuf;
+ int i, j;
+ struct page *page, **ppage;
+
+ for (i = 0; i < nr; i++) {
+ iobuf = iovec[i];
+
+ if (!iobuf->locked)
+ continue;
+ iobuf->locked = 0;
+
+ ppage = iobuf->maplist;
+ for (j = 0; j < iobuf->nr_pages; ppage++, j++) {
+ page = *ppage;
+ if (!page)
+ continue;
+ UnlockPage(page);
+ }
+ }
+ return 0;
+ }
+
+ static inline void zeromap_pte_range(pte_t * pte, unsigned long address,
+ unsigned long size, pgprot_t prot)
+ {
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ pte_t zero_pte = pte_wrprotect(mk_pte(ZERO_PAGE(address), prot));
+ pte_t oldpage = ptep_get_and_clear(pte);
+ set_pte(pte, zero_pte);
+ forget_pte(oldpage);
+ address += PAGE_SIZE;
+ pte++;
+ } while (address && (address < end));
+ }
+
+ static inline int zeromap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address,
+ unsigned long size, pgprot_t prot)
+ {
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ do {
+ pte_t * pte = pte_alloc(mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ zeromap_pte_range(pte, address, end - address, prot);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+ }
+
+ int zeromap_page_range(unsigned long address, unsigned long size, pgprot_t prot)
+ {
+ int error = 0;
+ pgd_t * dir;
+ unsigned long beg = address;
+ unsigned long end = address + size;
+ struct mm_struct *mm = current->mm;
+
+ dir = pgd_offset(mm, address);
+ flush_cache_range(mm, beg, end);
+ if (address >= end)
+ BUG();
+
+ spin_lock(&mm->page_table_lock);
+ do {
+ pmd_t *pmd = pmd_alloc(mm, dir, address);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ error = zeromap_pmd_range(mm, pmd, address, end - address, prot);
+ if (error)
+ break;
+ address = (address + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (address && (address < end));
+ spin_unlock(&mm->page_table_lock);
+ flush_tlb_range(mm, beg, end);
+ return error;
+ }
+
+ /*
+ * maps a range of physical memory into the requested pages. the old
+ * mappings are removed. any references to nonexistent pages results
+ * in null mappings (currently treated as "copy-on-access")
+ */
+ static inline void remap_pte_range(pte_t * pte, unsigned long address, unsigned long size,
+ unsigned long phys_addr, pgprot_t prot)
+ {
+ unsigned long end;
+
+ address &= ~PMD_MASK;
+ end = address + size;
+ if (end > PMD_SIZE)
+ end = PMD_SIZE;
+ do {
+ struct page *page;
+ pte_t oldpage;
+ oldpage = ptep_get_and_clear(pte);
+
+ page = virt_to_page(__va(phys_addr));
+ if ((!VALID_PAGE(page)) || PageReserved(page))
+ set_pte(pte, mk_pte_phys(phys_addr, prot));
+ forget_pte(oldpage);
+ address += PAGE_SIZE;
+ phys_addr += PAGE_SIZE;
+ pte++;
+ } while (address && (address < end));
+ }
+
+ static inline int remap_pmd_range(struct mm_struct *mm, pmd_t * pmd, unsigned long address, unsigned long size,
+ unsigned long phys_addr, pgprot_t prot)
+ {
+ unsigned long end;
+
+ address &= ~PGDIR_MASK;
+ end = address + size;
+ if (end > PGDIR_SIZE)
+ end = PGDIR_SIZE;
+ phys_addr -= address;
+ do {
+ pte_t * pte = pte_alloc(mm, pmd, address);
+ if (!pte)
+ return -ENOMEM;
+ remap_pte_range(pte, address, end - address, address + phys_addr, prot);
+ address = (address + PMD_SIZE) & PMD_MASK;
+ pmd++;
+ } while (address && (address < end));
+ return 0;
+ }
+
+ /* Note: this is only safe if the mm semaphore is held when called. */
+ int remap_page_range(unsigned long from, unsigned long phys_addr, unsigned long size, pgprot_t prot)
+ {
+ int error = 0;
+ pgd_t * dir;
+ unsigned long beg = from;
+ unsigned long end = from + size;
+ struct mm_struct *mm = current->mm;
+
+ phys_addr -= from;
+ dir = pgd_offset(mm, from);
+ flush_cache_range(mm, beg, end);
+ if (from >= end)
+ BUG();
+
+ spin_lock(&mm->page_table_lock);
+ do {
+ pmd_t *pmd = pmd_alloc(mm, dir, from);
+ error = -ENOMEM;
+ if (!pmd)
+ break;
+ error = remap_pmd_range(mm, pmd, from, end - from, phys_addr + from, prot);
+ if (error)
+ break;
+ from = (from + PGDIR_SIZE) & PGDIR_MASK;
+ dir++;
+ } while (from && (from < end));
+ spin_unlock(&mm->page_table_lock);
+ flush_tlb_range(mm, beg, end);
+ return error;
+ }
+
+ /*
+ * Establish a new mapping:
+ * - flush the old one
+ * - update the page tables
+ * - inform the TLB about the new one
+ *
+ * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
+ */
+ static inline void establish_pte(struct vm_area_struct * vma, unsigned long address, pte_t *page_table, pte_t entry)
+ {
+ #ifdef CONFIG_XEN
+ if ( likely(vma->vm_mm == current->mm) ) {
- if ( likely(vma->vm_mm == current->mm) ) {
- XEN_flush_page_update_queue();
- HYPERVISOR_update_va_mapping(address>>PAGE_SHIFT, pte, 0);
- } else {
++ HYPERVISOR_update_va_mapping(address, entry, UVMF_INVLPG|UVMF_LOCAL);
+ } else {
+ set_pte(page_table, entry);
+ flush_tlb_page(vma, address);
+ }
+ #else
+ set_pte(page_table, entry);
+ flush_tlb_page(vma, address);
+ #endif
+ update_mmu_cache(vma, address, entry);
+ }
+
+ /*
+ * We hold the mm semaphore for reading and vma->vm_mm->page_table_lock
+ */
+ static inline void break_cow(struct vm_area_struct * vma, struct page * new_page, unsigned long address,
+ pte_t *page_table)
+ {
+ flush_page_to_ram(new_page);
+ flush_cache_page(vma, address);
+ establish_pte(vma, address, page_table, pte_mkwrite(pte_mkdirty(mk_pte(new_page, vma->vm_page_prot))));
+ }
+
+ /*
+ * This routine handles present pages, when users try to write
+ * to a shared page. It is done by copying the page to a new address
+ * and decrementing the shared-page counter for the old page.
+ *
+ * Goto-purists beware: the only reason for goto's here is that it results
+ * in better assembly code.. The "default" path will see no jumps at all.
+ *
+ * Note that this routine assumes that the protection checks have been
+ * done by the caller (the low-level page fault routine in most cases).
+ * Thus we can safely just mark it writable once we've done any necessary
+ * COW.
+ *
+ * We also mark the page dirty at this point even though the page will
+ * change only once the write actually happens. This avoids a few races,
+ * and potentially makes it more efficient.
+ *
+ * We hold the mm semaphore and the page_table_lock on entry and exit
+ * with the page_table_lock released.
+ */
+ static int do_wp_page(struct mm_struct *mm, struct vm_area_struct * vma,
+ unsigned long address, pte_t *page_table, pte_t pte)
+ {
+ struct page *old_page, *new_page;
+
+ old_page = pte_page(pte);
+ if (!VALID_PAGE(old_page))
+ goto bad_wp_page;
+
+ if (!TryLockPage(old_page)) {
+ int reuse = can_share_swap_page(old_page);
+ unlock_page(old_page);
+ if (reuse) {
+ flush_cache_page(vma, address);
+ establish_pte(vma, address, page_table, pte_mkyoung(pte_mkdirty(pte_mkwrite(pte))));
+ spin_unlock(&mm->page_table_lock);
+ return 1; /* Minor fault */
+ }
+ }
+
+ /*
+ * Ok, we need to copy. Oh, well..
+ */
+ page_cache_get(old_page);
+ spin_unlock(&mm->page_table_lock);
+
+ new_page = alloc_page(GFP_HIGHUSER);
+ if (!new_page)
+ goto no_mem;
+ copy_cow_page(old_page,new_page,address);
+
+ /*
+ * Re-check the pte - we dropped the lock
+ */
+ spin_lock(&mm->page_table_lock);
+ if (pte_same(*page_table, pte)) {
+ if (PageReserved(old_page))
+ ++mm->rss;
+ break_cow(vma, new_page, address, page_table);
+ if (vm_anon_lru)
+ lru_cache_add(new_page);
+
+ /* Free the old page.. */
+ new_page = old_page;
+ }
+ spin_unlock(&mm->page_table_lock);
+ page_cache_release(new_page);
+ page_cache_release(old_page);
+ return 1; /* Minor fault */
+
+ bad_wp_page:
+ spin_unlock(&mm->page_table_lock);
+ printk("do_wp_page: bogus page at address %08lx (page 0x%lx)\n",address,(unsigned long)old_page);
+ return -1;
+ no_mem:
+ page_cache_release(old_page);
+ return -1;
+ }
+
+ static void vmtruncate_list(struct vm_area_struct *mpnt, unsigned long pgoff)
+ {
+ do {
+ struct mm_struct *mm = mpnt->vm_mm;
+ unsigned long start = mpnt->vm_start;
+ unsigned long end = mpnt->vm_end;
+ unsigned long len = end - start;
+ unsigned long diff;
+
+ /* mapping wholly truncated? */
+ if (mpnt->vm_pgoff >= pgoff) {
+ zap_page_range(mm, start, len);
+ continue;
+ }
+
+ /* mapping wholly unaffected? */
+ len = len >> PAGE_SHIFT;
+ diff = pgoff - mpnt->vm_pgoff;
+ if (diff >= len)
+ continue;
+
+ /* Ok, partially affected.. */
+ start += diff << PAGE_SHIFT;
+ len = (len - diff) << PAGE_SHIFT;
+ zap_page_range(mm, start, len);
+ } while ((mpnt = mpnt->vm_next_share) != NULL);
+ }
+
+ /*
+ * Handle all mappings that got truncated by a "truncate()"
+ * system call.
+ *
+ * NOTE! We have to be ready to update the memory sharing
+ * between the file and the memory map for a potential last
+ * incomplete page. Ugly, but necessary.
+ */
+ int vmtruncate(struct inode * inode, loff_t offset)
+ {
+ unsigned long pgoff;
+ struct address_space *mapping = inode->i_mapping;
+ unsigned long limit;
+
+ if (inode->i_size < offset)
+ goto do_expand;
+ inode->i_size = offset;
+ spin_lock(&mapping->i_shared_lock);
+ if (!mapping->i_mmap && !mapping->i_mmap_shared)
+ goto out_unlock;
+
+ pgoff = (offset + PAGE_CACHE_SIZE - 1) >> PAGE_CACHE_SHIFT;
+ if (mapping->i_mmap != NULL)
+ vmtruncate_list(mapping->i_mmap, pgoff);
+ if (mapping->i_mmap_shared != NULL)
+ vmtruncate_list(mapping->i_mmap_shared, pgoff);
+
+ out_unlock:
+ spin_unlock(&mapping->i_shared_lock);
+ truncate_inode_pages(mapping, offset);
+ goto out_truncate;
+
+ do_expand:
+ limit = current->rlim[RLIMIT_FSIZE].rlim_cur;
+ if (limit != RLIM_INFINITY && offset > limit)
+ goto out_sig;
+ if (offset > inode->i_sb->s_maxbytes)
+ goto out;
+ inode->i_size = offset;
+
+ out_truncate:
+ if (inode->i_op && inode->i_op->truncate) {
+ lock_kernel();
+ inode->i_op->truncate(inode);
+ unlock_kernel();
+ }
+ return 0;
+ out_sig:
+ send_sig(SIGXFSZ, current, 0);
+ out:
+ return -EFBIG;
+ }
+
+ /*
+ * Primitive swap readahead code. We simply read an aligned block of
+ * (1 << page_cluster) entries in the swap area. This method is chosen
+ * because it doesn't cost us any seek time. We also make sure to queue
+ * the 'original' request together with the readahead ones...
+ */
+ void swapin_readahead(swp_entry_t entry)
+ {
+ int i, num;
+ struct page *new_page;
+ unsigned long offset;
+
+ /*
+ * Get the number of handles we should do readahead io to.
+ */
+ num = valid_swaphandles(entry, &offset);
+ for (i = 0; i < num; offset++, i++) {
+ /* Ok, do the async read-ahead now */
+ new_page = read_swap_cache_async(SWP_ENTRY(SWP_TYPE(entry), offset));
+ if (!new_page)
+ break;
+ page_cache_release(new_page);
+ }
+ return;
+ }
+
+ /*
+ * We hold the mm semaphore and the page_table_lock on entry and
+ * should release the pagetable lock on exit..
+ */
+ static int do_swap_page(struct mm_struct * mm,
+ struct vm_area_struct * vma, unsigned long address,
+ pte_t * page_table, pte_t orig_pte, int write_access)
+ {
+ struct page *page;
+ swp_entry_t entry = pte_to_swp_entry(orig_pte);
+ pte_t pte;
+ int ret = 1;
+
+ spin_unlock(&mm->page_table_lock);
+ page = lookup_swap_cache(entry);
+ if (!page) {
+ swapin_readahead(entry);
+ page = read_swap_cache_async(entry);
+ if (!page) {
+ /*
+ * Back out if somebody else faulted in this pte while
+ * we released the page table lock.
+ */
+ int retval;
+ spin_lock(&mm->page_table_lock);
+ retval = pte_same(*page_table, orig_pte) ? -1 : 1;
+ spin_unlock(&mm->page_table_lock);
+ return retval;
+ }
+
+ /* Had to read the page from swap area: Major fault */
+ ret = 2;
+ }
+
+ mark_page_accessed(page);
+
+ lock_page(page);
+
+ /*
+ * Back out if somebody else faulted in this pte while we
+ * released the page table lock.
+ */
+ spin_lock(&mm->page_table_lock);
+ if (!pte_same(*page_table, orig_pte)) {
+ spin_unlock(&mm->page_table_lock);
+ unlock_page(page);
+ page_cache_release(page);
+ return 1;
+ }
+
+ /* The page isn't present yet, go ahead with the fault. */
+
+ swap_free(entry);
+ if (vm_swap_full())
+ remove_exclusive_swap_page(page);
+
+ mm->rss++;
+ pte = mk_pte(page, vma->vm_page_prot);
+ if (write_access && can_share_swap_page(page))
+ pte = pte_mkdirty(pte_mkwrite(pte));
+ unlock_page(page);
+
+ flush_page_to_ram(page);
+ flush_icache_page(vma, page);
+ #ifdef CONFIG_XEN
- XEN_flush_page_update_queue();
- }
++ if ( likely(vma->vm_mm == current->mm) )
++ HYPERVISOR_update_va_mapping(address, pte, 0);
++ else
+ set_pte(page_table, pte);
- if ( likely(vma->vm_mm == current->mm) ) {
- XEN_flush_page_update_queue();
- HYPERVISOR_update_va_mapping(addr>>PAGE_SHIFT, entry, 0);
- } else {
+ #else
+ set_pte(page_table, pte);
+ #endif
+
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, address, pte);
+ spin_unlock(&mm->page_table_lock);
+ return ret;
+ }
+
+ /*
+ * We are called with the MM semaphore and page_table_lock
+ * spinlock held to protect against concurrent faults in
+ * multithreaded programs.
+ */
+ static int do_anonymous_page(struct mm_struct * mm, struct vm_area_struct * vma, pte_t *page_table, int write_access, unsigned long addr)
+ {
+ pte_t entry;
+
+ /* Read-only mapping of ZERO_PAGE. */
+ entry = pte_wrprotect(mk_pte(ZERO_PAGE(addr), vma->vm_page_prot));
+
+ /* ..except if it's a write access */
+ if (write_access) {
+ struct page *page;
+
+ /* Allocate our own private page. */
+ spin_unlock(&mm->page_table_lock);
+
+ page = alloc_page(GFP_HIGHUSER);
+ if (!page)
+ goto no_mem;
+ clear_user_highpage(page, addr);
+
+ spin_lock(&mm->page_table_lock);
+ if (!pte_none(*page_table)) {
+ page_cache_release(page);
+ spin_unlock(&mm->page_table_lock);
+ return 1;
+ }
+ mm->rss++;
+ flush_page_to_ram(page);
+ entry = pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+ if (vm_anon_lru)
+ lru_cache_add(page);
+ mark_page_accessed(page);
+ }
+
+ #ifdef CONFIG_XEN
- XEN_flush_page_update_queue();
- }
++ if ( likely(vma->vm_mm == current->mm) )
++ HYPERVISOR_update_va_mapping(addr, entry, 0);
++ else
+ set_pte(page_table, entry);
- if ( likely(vma->vm_mm == current->mm) ) {
- XEN_flush_page_update_queue();
- HYPERVISOR_update_va_mapping(address>>PAGE_SHIFT, entry, 0);
- } else {
+ #else
+ set_pte(page_table, entry);
+ #endif
+
+ /* No need to invalidate - it was non-present before */
+ update_mmu_cache(vma, addr, entry);
+ spin_unlock(&mm->page_table_lock);
+ return 1; /* Minor fault */
+
+ no_mem:
+ return -1;
+ }
+
+ /*
+ * do_no_page() tries to create a new page mapping. It aggressively
+ * tries to share with existing pages, but makes a separate copy if
+ * the "write_access" parameter is true in order to avoid the next
+ * page fault.
+ *
+ * As this is called only for pages that do not currently exist, we
+ * do not need to flush old virtual caches or the TLB.
+ *
+ * This is called with the MM semaphore held and the page table
+ * spinlock held. Exit with the spinlock released.
+ */
+ static int do_no_page(struct mm_struct * mm, struct vm_area_struct * vma,
+ unsigned long address, int write_access, pte_t *page_table)
+ {
+ struct page * new_page;
+ pte_t entry;
+
+ if (!vma->vm_ops || !vma->vm_ops->nopage)
+ return do_anonymous_page(mm, vma, page_table, write_access, address);
+ spin_unlock(&mm->page_table_lock);
+
+ new_page = vma->vm_ops->nopage(vma, address & PAGE_MASK, 0);
+
+ if (new_page == NULL) /* no page was available -- SIGBUS */
+ return 0;
+ if (new_page == NOPAGE_OOM)
+ return -1;
+
+ /*
+ * Should we do an early C-O-W break?
+ */
+ if (write_access && !(vma->vm_flags & VM_SHARED)) {
+ struct page * page = alloc_page(GFP_HIGHUSER);
+ if (!page) {
+ page_cache_release(new_page);
+ return -1;
+ }
+ copy_user_highpage(page, new_page, address);
+ page_cache_release(new_page);
+ if (vm_anon_lru)
+ lru_cache_add(page);
+ new_page = page;
+ }
+
+ spin_lock(&mm->page_table_lock);
+ /*
+ * This silly early PAGE_DIRTY setting removes a race
+ * due to the bad i386 page protection. But it's valid
+ * for other architectures too.
+ *
+ * Note that if write_access is true, we either now have
+ * an exclusive copy of the page, or this is a shared mapping,
+ * so we can make it writable and dirty to avoid having to
+ * handle that later.
+ */
+ /* Only go through if we didn't race with anybody else... */
+ if (pte_none(*page_table)) {
+ if (!PageReserved(new_page))
+ ++mm->rss;
+ flush_page_to_ram(new_page);
+ flush_icache_page(vma, new_page);
+ entry = mk_pte(new_page, vma->vm_page_prot);
+ if (write_access)
+ entry = pte_mkwrite(pte_mkdirty(entry));
+ #ifdef CONFIG_XEN
- XEN_flush_page_update_queue();
- }
++ if ( likely(vma->vm_mm == current->mm) )
++ HYPERVISOR_update_va_mapping(address, entry, 0);
++ else
+ set_pte(page_table, entry);
- XEN_flush_page_update_queue();
+ #else
+ set_pte(page_table, entry);
+ #endif
+ } else {
+ /* One of our sibling threads was faster, back out. */
+ page_cache_release(new_page);
+ spin_unlock(&mm->page_table_lock);
+ return 1;
+ }
+
+ /* no need to invalidate: a not-present page shouldn't be cached */
+ update_mmu_cache(vma, address, entry);
+ spin_unlock(&mm->page_table_lock);
+ return 2; /* Major fault */
+ }
+
+ /*
+ * These routines also need to handle stuff like marking pages dirty
+ * and/or accessed for architectures that don't do it in hardware (most
+ * RISC architectures). The early dirtying is also good on the i386.
+ *
+ * There is also a hook called "update_mmu_cache()" that architectures
+ * with external mmu caches can use to update those (ie the Sparc or
+ * PowerPC hashed page tables that act as extended TLBs).
+ *
+ * Note the "page_table_lock". It is to protect against kswapd removing
+ * pages from under us. Note that kswapd only ever _removes_ pages, never
+ * adds them. As such, once we have noticed that the page is not present,
+ * we can drop the lock early.
+ *
+ * The adding of pages is protected by the MM semaphore (which we hold),
+ * so we don't need to worry about a page being suddenly been added into
+ * our VM.
+ *
+ * We enter with the pagetable spinlock held, we are supposed to
+ * release it when done.
+ */
+ static inline int handle_pte_fault(struct mm_struct *mm,
+ struct vm_area_struct * vma, unsigned long address,
+ int write_access, pte_t * pte)
+ {
+ pte_t entry;
+
+ entry = *pte;
+ if (!pte_present(entry)) {
+ /*
+ * If it truly wasn't present, we know that kswapd
+ * and the PTE updates will not touch it later. So
+ * drop the lock.
+ */
+ if (pte_none(entry))
+ return do_no_page(mm, vma, address, write_access, pte);
+ return do_swap_page(mm, vma, address, pte, entry, write_access);
+ }
+
+ if (write_access) {
+ if (!pte_write(entry))
+ return do_wp_page(mm, vma, address, pte, entry);
+
+ entry = pte_mkdirty(entry);
+ }
+ entry = pte_mkyoung(entry);
+ establish_pte(vma, address, pte, entry);
+ spin_unlock(&mm->page_table_lock);
+ return 1;
+ }
+
+ /*
+ * By the time we get here, we already hold the mm semaphore
+ */
+ int handle_mm_fault(struct mm_struct *mm, struct vm_area_struct * vma,
+ unsigned long address, int write_access)
+ {
+ pgd_t *pgd;
+ pmd_t *pmd;
+
+ current->state = TASK_RUNNING;
+ pgd = pgd_offset(mm, address);
+
+ /*
+ * We need the page table lock to synchronize with kswapd
+ * and the SMP-safe atomic PTE updates.
+ */
+ spin_lock(&mm->page_table_lock);
+ pmd = pmd_alloc(mm, pgd, address);
+
+ if (pmd) {
+ pte_t * pte = pte_alloc(mm, pmd, address);
+ if (pte)
+ return handle_pte_fault(mm, vma, address, write_access, pte);
+ }
+ spin_unlock(&mm->page_table_lock);
+ return -1;
+ }
+
+ /*
+ * Allocate page middle directory.
+ *
+ * We've already handled the fast-path in-line, and we own the
+ * page table lock.
+ *
+ * On a two-level page table, this ends up actually being entirely
+ * optimized away.
+ */
+ pmd_t fastcall *__pmd_alloc(struct mm_struct *mm, pgd_t *pgd, unsigned long address)
+ {
+ pmd_t *new;
+
+ /* "fast" allocation can happen without dropping the lock.. */
+ new = pmd_alloc_one_fast(mm, address);
+ if (!new) {
+ spin_unlock(&mm->page_table_lock);
+ new = pmd_alloc_one(mm, address);
+ spin_lock(&mm->page_table_lock);
+ if (!new)
+ return NULL;
+
+ /*
+ * Because we dropped the lock, we should re-check the
+ * entry, as somebody else could have populated it..
+ */
+ if (!pgd_none(*pgd)) {
+ pmd_free(new);
+ check_pgt_cache();
+ goto out;
+ }
+ }
+ pgd_populate(mm, pgd, new);
+ out:
+ return pmd_offset(pgd, address);
+ }
+
+ /*
+ * Allocate the page table directory.
+ *
+ * We've already handled the fast-path in-line, and we own the
+ * page table lock.
+ */
+ pte_t fastcall *pte_alloc(struct mm_struct *mm, pmd_t *pmd, unsigned long address)
+ {
+ if (pmd_none(*pmd)) {
+ pte_t *new;
+
+ /* "fast" allocation can happen without dropping the lock.. */
+ new = pte_alloc_one_fast(mm, address);
+ if (!new) {
+ spin_unlock(&mm->page_table_lock);
+ new = pte_alloc_one(mm, address);
+ spin_lock(&mm->page_table_lock);
+ if (!new)
+ return NULL;
+
+ /*
+ * Because we dropped the lock, we should re-check the
+ * entry, as somebody else could have populated it..
+ */
+ if (!pmd_none(*pmd)) {
+ pte_free(new);
+ check_pgt_cache();
+ goto out;
+ }
+ }
+ pmd_populate(mm, pmd, new);
+ }
+ out:
+ return pte_offset(pmd, address);
+ }
+
+ int make_pages_present(unsigned long addr, unsigned long end)
+ {
+ int ret, len, write;
+ struct vm_area_struct * vma;
+
+ vma = find_vma(current->mm, addr);
+ write = (vma->vm_flags & VM_WRITE) != 0;
+ if (addr >= end)
+ BUG();
+ if (end > vma->vm_end)
+ BUG();
+ len = (end+PAGE_SIZE-1)/PAGE_SIZE-addr/PAGE_SIZE;
+ ret = get_user_pages(current, current->mm, addr,
+ len, write, 0, NULL, NULL);
+ return ret == len ? 0 : -1;
+ }
+
+ struct page * vmalloc_to_page(void * vmalloc_addr)
+ {
+ unsigned long addr = (unsigned long) vmalloc_addr;
+ struct page *page = NULL;
+ pmd_t *pmd;
+ pte_t *pte;
+ pgd_t *pgd;
+
+ pgd = pgd_offset_k(addr);
+ if (!pgd_none(*pgd)) {
+ pmd = pmd_offset(pgd, addr);
+ if (!pmd_none(*pmd)) {
+ pte = pte_offset(pmd, addr);
+ if (pte_present(*pte)) {
+ page = pte_page(*pte);
+ }
+ }
+ }
+ return page;
+ }
--- /dev/null
- XEN_flush_page_update_queue();
+ /*
+ * linux/mm/remap.c
+ *
+ * (C) Copyright 1996 Linus Torvalds
+ */
+
+ #include <linux/slab.h>
+ #include <linux/smp_lock.h>
+ #include <linux/shm.h>
+ #include <linux/mman.h>
+ #include <linux/swap.h>
+
+ #include <asm/uaccess.h>
+ #include <asm/pgalloc.h>
+
+ extern int vm_enough_memory(long pages);
+
+ static inline pte_t *get_one_pte(struct mm_struct *mm, unsigned long addr)
+ {
+ pgd_t * pgd;
+ pmd_t * pmd;
+ pte_t * pte = NULL;
+
+ pgd = pgd_offset(mm, addr);
+ if (pgd_none(*pgd))
+ goto end;
+ if (pgd_bad(*pgd)) {
+ pgd_ERROR(*pgd);
+ pgd_clear(pgd);
+ goto end;
+ }
+
+ pmd = pmd_offset(pgd, addr);
+ if (pmd_none(*pmd))
+ goto end;
+ if (pmd_bad(*pmd)) {
+ pmd_ERROR(*pmd);
+ pmd_clear(pmd);
+ goto end;
+ }
+
+ pte = pte_offset(pmd, addr);
+ if (pte_none(*pte))
+ pte = NULL;
+ end:
+ return pte;
+ }
+
+ static inline pte_t *alloc_one_pte(struct mm_struct *mm, unsigned long addr)
+ {
+ pmd_t * pmd;
+ pte_t * pte = NULL;
+
+ pmd = pmd_alloc(mm, pgd_offset(mm, addr), addr);
+ if (pmd)
+ pte = pte_alloc(mm, pmd, addr);
+ return pte;
+ }
+
+ static inline int copy_one_pte(struct mm_struct *mm, pte_t * src, pte_t * dst)
+ {
+ int error = 0;
+ pte_t pte;
+
+ if (!pte_none(*src)) {
+ pte = ptep_get_and_clear(src);
+ if (!dst) {
+ /* No dest? We must put it back. */
+ dst = src;
+ error++;
+ }
+ set_pte(dst, pte);
+ }
+ return error;
+ }
+
+ static int move_one_page(struct mm_struct *mm, unsigned long old_addr, unsigned long new_addr)
+ {
+ int error = 0;
+ pte_t * src, * dst;
+
+ spin_lock(&mm->page_table_lock);
+ src = get_one_pte(mm, old_addr);
+ if (src) {
+ dst = alloc_one_pte(mm, new_addr);
+ src = get_one_pte(mm, old_addr);
+ if (src)
+ error = copy_one_pte(mm, src, dst);
+ }
+ spin_unlock(&mm->page_table_lock);
+ return error;
+ }
+
+ static int move_page_tables(struct mm_struct * mm,
+ unsigned long new_addr, unsigned long old_addr, unsigned long len)
+ {
+ unsigned long offset = len;
+
+ flush_cache_range(mm, old_addr, old_addr + len);
+
+ /*
+ * This is not the clever way to do this, but we're taking the
+ * easy way out on the assumption that most remappings will be
+ * only a few pages.. This also makes error recovery easier.
+ */
+ while (offset) {
+ offset -= PAGE_SIZE;
+ if (move_one_page(mm, old_addr + offset, new_addr + offset))
+ goto oops_we_failed;
+ }
+ flush_tlb_range(mm, old_addr, old_addr + len);
+ return 0;
+
+ /*
+ * Ok, the move failed because we didn't have enough pages for
+ * the new page table tree. This is unlikely, but we have to
+ * take the possibility into account. In that case we just move
+ * all the pages back (this will work, because we still have
+ * the old page tables)
+ */
+ oops_we_failed:
- XEN_flush_page_update_queue();
+ flush_cache_range(mm, new_addr, new_addr + len);
+ while ((offset += PAGE_SIZE) < len)
+ move_one_page(mm, new_addr + offset, old_addr + offset);
+ zap_page_range(mm, new_addr, len);
+ return -1;
+ }
+
+ static inline unsigned long move_vma(struct vm_area_struct * vma,
+ unsigned long addr, unsigned long old_len, unsigned long new_len,
+ unsigned long new_addr)
+ {
+ struct mm_struct * mm = vma->vm_mm;
+ struct vm_area_struct * new_vma, * next, * prev;
+ int allocated_vma;
+
+ new_vma = NULL;
+ next = find_vma_prev(mm, new_addr, &prev);
+ if (next) {
+ if (prev && prev->vm_end == new_addr &&
+ can_vma_merge(prev, vma->vm_flags) && !vma->vm_file && !(vma->vm_flags & VM_SHARED)) {
+ spin_lock(&mm->page_table_lock);
+ prev->vm_end = new_addr + new_len;
+ spin_unlock(&mm->page_table_lock);
+ new_vma = prev;
+ if (next != prev->vm_next)
+ BUG();
+ if (prev->vm_end == next->vm_start && can_vma_merge(next, prev->vm_flags)) {
+ spin_lock(&mm->page_table_lock);
+ prev->vm_end = next->vm_end;
+ __vma_unlink(mm, next, prev);
+ spin_unlock(&mm->page_table_lock);
+
+ mm->map_count--;
+ kmem_cache_free(vm_area_cachep, next);
+ }
+ } else if (next->vm_start == new_addr + new_len &&
+ can_vma_merge(next, vma->vm_flags) && !vma->vm_file && !(vma->vm_flags & VM_SHARED)) {
+ spin_lock(&mm->page_table_lock);
+ next->vm_start = new_addr;
+ spin_unlock(&mm->page_table_lock);
+ new_vma = next;
+ }
+ } else {
+ prev = find_vma(mm, new_addr-1);
+ if (prev && prev->vm_end == new_addr &&
+ can_vma_merge(prev, vma->vm_flags) && !vma->vm_file && !(vma->vm_flags & VM_SHARED)) {
+ spin_lock(&mm->page_table_lock);
+ prev->vm_end = new_addr + new_len;
+ spin_unlock(&mm->page_table_lock);
+ new_vma = prev;
+ }
+ }
+
+ allocated_vma = 0;
+ if (!new_vma) {
+ new_vma = kmem_cache_alloc(vm_area_cachep, SLAB_KERNEL);
+ if (!new_vma)
+ goto out;
+ allocated_vma = 1;
+ }
+
+ if (!move_page_tables(current->mm, new_addr, addr, old_len)) {
+ unsigned long vm_locked = vma->vm_flags & VM_LOCKED;
+
+ if (allocated_vma) {
+ *new_vma = *vma;
+ new_vma->vm_start = new_addr;
+ new_vma->vm_end = new_addr+new_len;
+ new_vma->vm_pgoff += (addr-vma->vm_start) >> PAGE_SHIFT;
+ new_vma->vm_raend = 0;
+ if (new_vma->vm_file)
+ get_file(new_vma->vm_file);
+ if (new_vma->vm_ops && new_vma->vm_ops->open)
+ new_vma->vm_ops->open(new_vma);
+ insert_vm_struct(current->mm, new_vma);
+ }
+
+ /* XXX: possible errors masked, mapping might remain */
+ do_munmap(current->mm, addr, old_len);
+
+ current->mm->total_vm += new_len >> PAGE_SHIFT;
+ if (vm_locked) {
+ current->mm->locked_vm += new_len >> PAGE_SHIFT;
+ if (new_len > old_len)
+ make_pages_present(new_addr + old_len,
+ new_addr + new_len);
+ }
+ return new_addr;
+ }
+ if (allocated_vma)
+ kmem_cache_free(vm_area_cachep, new_vma);
+ out:
+ return -ENOMEM;
+ }
+
+ /*
+ * Expand (or shrink) an existing mapping, potentially moving it at the
+ * same time (controlled by the MREMAP_MAYMOVE flag and available VM space)
+ *
+ * MREMAP_FIXED option added 5-Dec-1999 by Benjamin LaHaise
+ * This option implies MREMAP_MAYMOVE.
+ */
+ unsigned long do_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr)
+ {
+ struct vm_area_struct *vma;
+ unsigned long ret = -EINVAL;
+
+ if (flags & ~(MREMAP_FIXED | MREMAP_MAYMOVE))
+ goto out;
+
+ if (addr & ~PAGE_MASK)
+ goto out;
+
+ old_len = PAGE_ALIGN(old_len);
+ new_len = PAGE_ALIGN(new_len);
+
+ if (old_len > TASK_SIZE || addr > TASK_SIZE - old_len)
+ goto out;
+
+ if (addr >= TASK_SIZE)
+ goto out;
+
+ /* new_addr is only valid if MREMAP_FIXED is specified */
+ if (flags & MREMAP_FIXED) {
+ if (new_addr & ~PAGE_MASK)
+ goto out;
+ if (!(flags & MREMAP_MAYMOVE))
+ goto out;
+
+ if (new_len > TASK_SIZE || new_addr > TASK_SIZE - new_len)
+ goto out;
+
+ if (new_addr >= TASK_SIZE)
+ goto out;
+
+ /*
+ * Allow new_len == 0 only if new_addr == addr
+ * to preserve truncation in place (that was working
+ * safe and some app may depend on it).
+ */
+ if (unlikely(!new_len && new_addr != addr))
+ goto out;
+
+ /* Check if the location we're moving into overlaps the
+ * old location at all, and fail if it does.
+ */
+ if ((new_addr <= addr) && (new_addr+new_len) > addr)
+ goto out;
+
+ if ((addr <= new_addr) && (addr+old_len) > new_addr)
+ goto out;
+
+ ret = do_munmap(current->mm, new_addr, new_len);
+ if (ret && new_len)
+ goto out;
+ }
+
+ /*
+ * Always allow a shrinking remap: that just unmaps
+ * the unnecessary pages..
+ */
+ if (old_len >= new_len) {
+ ret = do_munmap(current->mm, addr+new_len, old_len - new_len);
+ if (ret && old_len != new_len)
+ goto out;
+ ret = addr;
+ if (!(flags & MREMAP_FIXED) || (new_addr == addr))
+ goto out;
+ }
+
+ /*
+ * Ok, we need to grow.. or relocate.
+ */
+ ret = -EFAULT;
+ vma = find_vma(current->mm, addr);
+ if (!vma || vma->vm_start > addr)
+ goto out;
+ /* We can't remap across vm area boundaries */
+ if (old_len > vma->vm_end - addr)
+ goto out;
+ if (vma->vm_flags & VM_DONTEXPAND) {
+ if (new_len > old_len)
+ goto out;
+ }
+ if (vma->vm_flags & VM_LOCKED) {
+ unsigned long locked = current->mm->locked_vm << PAGE_SHIFT;
+ locked += new_len - old_len;
+ ret = -EAGAIN;
+ if (locked > current->rlim[RLIMIT_MEMLOCK].rlim_cur)
+ goto out;
+ }
+ ret = -ENOMEM;
+ if ((current->mm->total_vm << PAGE_SHIFT) + (new_len - old_len)
+ > current->rlim[RLIMIT_AS].rlim_cur)
+ goto out;
+ /* Private writable mapping? Check memory availability.. */
+ if ((vma->vm_flags & (VM_SHARED | VM_WRITE)) == VM_WRITE &&
+ !(flags & MAP_NORESERVE) &&
+ !vm_enough_memory((new_len - old_len) >> PAGE_SHIFT))
+ goto out;
+
+ #if defined(CONFIG_XEN_PRIVILEGED_GUEST)
+ /* mremap() unsupported for I/O mappings in Xenolinux. */
+ ret = -EINVAL;
+ if (vma->vm_flags & VM_IO)
+ goto out;
+ #endif
+
+ /* old_len exactly to the end of the area..
+ * And we're not relocating the area.
+ */
+ if (old_len == vma->vm_end - addr &&
+ !((flags & MREMAP_FIXED) && (addr != new_addr)) &&
+ (old_len != new_len || !(flags & MREMAP_MAYMOVE))) {
+ unsigned long max_addr = TASK_SIZE;
+ if (vma->vm_next)
+ max_addr = vma->vm_next->vm_start;
+ /* can we just expand the current mapping? */
+ if (max_addr - addr >= new_len) {
+ int pages = (new_len - old_len) >> PAGE_SHIFT;
+ spin_lock(&vma->vm_mm->page_table_lock);
+ vma->vm_end = addr + new_len;
+ spin_unlock(&vma->vm_mm->page_table_lock);
+ current->mm->total_vm += pages;
+ if (vma->vm_flags & VM_LOCKED) {
+ current->mm->locked_vm += pages;
+ make_pages_present(addr + old_len,
+ addr + new_len);
+ }
+ ret = addr;
+ goto out;
+ }
+ }
+
+ /*
+ * We weren't able to just expand or shrink the area,
+ * we need to create a new one and move it..
+ */
+ ret = -ENOMEM;
+ if (flags & MREMAP_MAYMOVE) {
+ if (!(flags & MREMAP_FIXED)) {
+ unsigned long map_flags = 0;
+ if (vma->vm_flags & VM_SHARED)
+ map_flags |= MAP_SHARED;
+
+ new_addr = get_unmapped_area(vma->vm_file, 0, new_len, vma->vm_pgoff, map_flags);
+ ret = new_addr;
+ if (new_addr & ~PAGE_MASK)
+ goto out;
+ }
+ ret = move_vma(vma, addr, old_len, new_len, new_addr);
+ }
+ out:
+ return ret;
+ }
+
+ asmlinkage unsigned long sys_mremap(unsigned long addr,
+ unsigned long old_len, unsigned long new_len,
+ unsigned long flags, unsigned long new_addr)
+ {
+ unsigned long ret;
+
+ down_write(¤t->mm->mmap_sem);
+ ret = do_mremap(addr, old_len, new_len, flags, new_addr);
+ up_write(¤t->mm->mmap_sem);
+ return ret;
+ }